mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 18:22:42 +00:00
Add evidence-backed investigation workflows
This commit is contained in:
1 parent
4110a4d717
commit
4ff4c11a00
178 files changed
+26320
-1222
No files matched your search
@@ -0,0 +1,77 @@
|
||||
import type {
|
||||
ProcessCapture,
|
||||
ProcessSample,
|
||||
ProcessScenario,
|
||||
} from "../domain/processCapture.js";
|
||||
|
||||
/** Normalize and redact one terminal/protocol payload under scenario rules. */
|
||||
export const normalizeProcessText = (
|
||||
value: string,
|
||||
scenario: ProcessScenario,
|
||||
temporaryRoot: string,
|
||||
pid: number,
|
||||
): string => {
|
||||
let normalized = value;
|
||||
for (const alias of scenario.secret_aliases) {
|
||||
const secret = scenario.environment[alias];
|
||||
if (secret !== undefined && secret.length > 0)
|
||||
normalized = normalized.replaceAll(secret, "<redacted>");
|
||||
}
|
||||
if (scenario.normalization.paths) {
|
||||
normalized = normalized.replaceAll(temporaryRoot, "<temporary-root>");
|
||||
normalized = normalized.replaceAll(
|
||||
scenario.working_directory,
|
||||
"<working-directory>",
|
||||
);
|
||||
normalized = normalized.replaceAll(scenario.executable, "<executable>");
|
||||
for (const [index, root] of scenario.filesystem_roots.entries())
|
||||
normalized = normalized.replaceAll(
|
||||
root,
|
||||
`<filesystem-root-${String(index)}>`,
|
||||
);
|
||||
}
|
||||
if (scenario.normalization.pids)
|
||||
normalized = normalized.replaceAll(String(pid), "<pid>");
|
||||
if (scenario.normalization.ports)
|
||||
normalized = normalized.replaceAll(/(?<=[:=])\d{2,5}\b/g, "<port>");
|
||||
for (const pattern of scenario.normalization.patterns)
|
||||
normalized = normalized.replaceAll(pattern.pattern, pattern.replacement);
|
||||
return normalized;
|
||||
};
|
||||
|
||||
export const normalizeProcessSamples = (
|
||||
samples: readonly ProcessSample[],
|
||||
scenario: ProcessScenario,
|
||||
rootPid: number,
|
||||
): readonly ProcessSample[] => {
|
||||
const identifiers = [
|
||||
rootPid,
|
||||
...samples.flatMap((sample) => [sample.pid, sample.parent_pid]),
|
||||
];
|
||||
const mapping = new Map<number, number>();
|
||||
for (const identifier of identifiers)
|
||||
if (identifier > 0 && !mapping.has(identifier))
|
||||
mapping.set(identifier, mapping.size + 1);
|
||||
return samples.map((sample) => ({
|
||||
at_ms:
|
||||
Math.floor(sample.at_ms / scenario.normalization.time_bucket_ms) *
|
||||
scenario.normalization.time_bucket_ms,
|
||||
pid: mapping.get(sample.pid) ?? 1,
|
||||
parent_pid: mapping.get(sample.parent_pid) ?? 0,
|
||||
command: normalizeProcessText(
|
||||
sample.command,
|
||||
scenario,
|
||||
"<no-temporary-root>",
|
||||
rootPid,
|
||||
),
|
||||
}));
|
||||
};
|
||||
|
||||
export const redactProtocolEvents = (
|
||||
events: readonly ProcessCapture["protocol_events"][number][],
|
||||
scenario: ProcessScenario,
|
||||
): readonly ProcessCapture["protocol_events"][number][] =>
|
||||
events.map((event) => ({
|
||||
...event,
|
||||
data: normalizeProcessText(event.data, scenario, "<no-temporary-root>", -1),
|
||||
}));
|
||||
Reference in new issue
Block a user