rea-agents 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -31
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/Doctor.js +56 -6
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +38 -13
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +7 -1
- package/dist/application/JavaScriptArtifactGraphBuilder.js +59 -16
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactReconstruction.js +3 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/runtime.js +2 -0
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +4 -1
- package/dist/cli.js +388 -0
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliCommandNames.js +13 -0
- package/dist/cliElectronCommands.js +103 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/config.js +83 -0
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +47 -45
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +46 -31
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +67 -1
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +31 -43
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +10 -0
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraProvider.js +6 -0
- package/dist/main.js +14 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +52 -0
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +58 -13
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +8 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +51 -86
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +12 -4
- package/scripts/rea.mjs +1 -1
- package/skills/rea-analysis/SKILL.md +59 -3
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { compareManagedMembers, managedMemberComparisonResultSchema, parseManagedMemberEvidence, } from "../domain/managedMemberComparison.js";
|
|
4
|
+
import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
|
|
5
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
6
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
7
|
+
import { parseBinaryTarget } from "../domain/binaryTarget.js";
|
|
8
|
+
import { err, ok } from "../domain/result.js";
|
|
9
|
+
import { inspectManagedMembersBytes } from "../dotnet/ManagedMemberInspector.js";
|
|
10
|
+
import { MANAGED_STATIC_PROVIDER } from "./InvestigationProviders.js";
|
|
11
|
+
import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
12
|
+
/** Compare managed members from input parsed by a trusted adapter. */
|
|
13
|
+
export const compareManagedMembersEvidenceValidated = (input) => {
|
|
14
|
+
const operation = "compare_managed_members";
|
|
15
|
+
try {
|
|
16
|
+
const left = parseManagedMemberEvidence(input.left);
|
|
17
|
+
const right = parseManagedMemberEvidence(input.right);
|
|
18
|
+
const result = compareManagedMembers({ evidenceId: left.evidenceId, result: left.result }, { evidenceId: right.evidenceId, result: right.result }, input.limits);
|
|
19
|
+
return ok(createManagedMemberComparisonEvidence(input, result));
|
|
20
|
+
}
|
|
21
|
+
catch (cause) {
|
|
22
|
+
return workflowFailure(operation, cause);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/** Inspect two local PE artifacts and return one derived comparison Evidence. */
|
|
26
|
+
export const compareManagedMemberPaths = async (input) => {
|
|
27
|
+
const operation = "compare_managed_members";
|
|
28
|
+
try {
|
|
29
|
+
const [leftTarget, rightTarget] = await Promise.all([
|
|
30
|
+
parseBinaryTarget(input.leftPath),
|
|
31
|
+
parseBinaryTarget(input.rightPath),
|
|
32
|
+
]);
|
|
33
|
+
if (!leftTarget.ok)
|
|
34
|
+
return err(new AnalysisInputError(operation, { cause: leftTarget.error }));
|
|
35
|
+
if (!rightTarget.ok)
|
|
36
|
+
return err(new AnalysisInputError(operation, { cause: rightTarget.error }));
|
|
37
|
+
const [leftStat, rightStat] = await Promise.all([
|
|
38
|
+
stat(leftTarget.value.path),
|
|
39
|
+
stat(rightTarget.value.path),
|
|
40
|
+
]);
|
|
41
|
+
if (leftStat.size > input.memberLimits.maxFileBytes ||
|
|
42
|
+
rightStat.size > input.memberLimits.maxFileBytes)
|
|
43
|
+
return err(new AnalysisInputError(operation, {
|
|
44
|
+
cause: new RangeError(`Managed comparison input exceeds max_file_bytes ${String(input.memberLimits.maxFileBytes)}`),
|
|
45
|
+
}));
|
|
46
|
+
const [leftBytes, rightBytes] = await Promise.all([
|
|
47
|
+
readFile(leftTarget.value.path),
|
|
48
|
+
readFile(rightTarget.value.path),
|
|
49
|
+
]);
|
|
50
|
+
const leftInspection = inspectManagedMembersBytes(leftBytes, leftTarget.value, input.memberLimits);
|
|
51
|
+
const rightInspection = inspectManagedMembersBytes(rightBytes, rightTarget.value, input.memberLimits);
|
|
52
|
+
const leftEvidence = createEvidence(leftTarget.value, MANAGED_STATIC_PROVIDER, {
|
|
53
|
+
operation: "inspect_managed_members",
|
|
54
|
+
parameters: memberLimitParameters(input.memberLimits),
|
|
55
|
+
result: jsonValueSchema.parse(leftInspection),
|
|
56
|
+
rawResult: null,
|
|
57
|
+
limitations: leftInspection.limitations,
|
|
58
|
+
locations: [{ kind: "artifact-path", path: leftTarget.value.path }],
|
|
59
|
+
});
|
|
60
|
+
const rightEvidence = createEvidence(rightTarget.value, MANAGED_STATIC_PROVIDER, {
|
|
61
|
+
operation: "inspect_managed_members",
|
|
62
|
+
parameters: memberLimitParameters(input.memberLimits),
|
|
63
|
+
result: jsonValueSchema.parse(rightInspection),
|
|
64
|
+
rawResult: null,
|
|
65
|
+
limitations: rightInspection.limitations,
|
|
66
|
+
locations: [{ kind: "artifact-path", path: rightTarget.value.path }],
|
|
67
|
+
});
|
|
68
|
+
const result = compareManagedMembers({
|
|
69
|
+
evidenceId: leftEvidence.evidence_id,
|
|
70
|
+
result: leftInspection,
|
|
71
|
+
}, {
|
|
72
|
+
evidenceId: rightEvidence.evidence_id,
|
|
73
|
+
result: rightInspection,
|
|
74
|
+
}, input.comparisonLimits);
|
|
75
|
+
return ok(createManagedMemberComparisonEvidence({
|
|
76
|
+
left: leftEvidence,
|
|
77
|
+
right: rightEvidence,
|
|
78
|
+
limits: input.comparisonLimits,
|
|
79
|
+
}, result));
|
|
80
|
+
}
|
|
81
|
+
catch (cause) {
|
|
82
|
+
return workflowFailure(operation, cause);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const createManagedMemberComparisonEvidence = (parameters, result) => createEvidence(undefined, MANAGED_WORKFLOW_PROVIDER, {
|
|
86
|
+
predicateType: "rea.managed-member-comparison/v1",
|
|
87
|
+
operation: "compare_managed_members",
|
|
88
|
+
parameters: {
|
|
89
|
+
left_evidence_id: parameters.left.evidence_id,
|
|
90
|
+
right_evidence_id: parameters.right.evidence_id,
|
|
91
|
+
limits: jsonValueSchema.parse(parameters.limits),
|
|
92
|
+
},
|
|
93
|
+
result: jsonValueSchema.parse(result),
|
|
94
|
+
rawResult: null,
|
|
95
|
+
confidence: "inferred",
|
|
96
|
+
authority: "analyst-inference",
|
|
97
|
+
environment: null,
|
|
98
|
+
limitations: result.limitations,
|
|
99
|
+
evidenceLinks: result.evidence_links,
|
|
100
|
+
});
|
|
101
|
+
const memberLimitParameters = (limits) => ({
|
|
102
|
+
type_offset: limits.typeOffset,
|
|
103
|
+
type_limit: limits.typeLimit,
|
|
104
|
+
method_offset: limits.methodOffset,
|
|
105
|
+
method_limit: limits.methodLimit,
|
|
106
|
+
field_offset: limits.fieldOffset,
|
|
107
|
+
field_limit: limits.fieldLimit,
|
|
108
|
+
member_ref_offset: limits.memberRefOffset,
|
|
109
|
+
member_ref_limit: limits.memberRefLimit,
|
|
110
|
+
edge_offset: limits.edgeOffset,
|
|
111
|
+
edge_limit: limits.edgeLimit,
|
|
112
|
+
instruction_anchor_limit: limits.instructionAnchorLimit,
|
|
113
|
+
max_file_bytes: limits.maxFileBytes,
|
|
114
|
+
max_metadata_bytes: limits.maxMetadataBytes,
|
|
115
|
+
max_table_rows: limits.maxTableRows,
|
|
116
|
+
max_heap_item_bytes: limits.maxHeapItemBytes,
|
|
117
|
+
max_method_body_bytes: limits.maxMethodBodyBytes,
|
|
118
|
+
max_method_instructions: limits.maxMethodInstructions,
|
|
119
|
+
});
|
|
120
|
+
const workflowFailure = (operation, cause) => err(cause instanceof z.ZodError || cause instanceof TypeError
|
|
121
|
+
? new AnalysisInputError(operation, { cause })
|
|
122
|
+
: new AnalysisProtocolError("Managed member comparison produced an invalid result", { cause }));
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
|
|
3
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
4
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
|
+
import { managedNativeVerificationInputSchema, verifyManagedNativeBoundaries, } from "../domain/managedNativeVerification.js";
|
|
6
|
+
import { err, ok } from "../domain/result.js";
|
|
7
|
+
import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
8
|
+
const OPERATION = "verify_managed_native_boundaries";
|
|
9
|
+
/** Verify managed/native boundary declarations against native Evidence. */
|
|
10
|
+
export const verifyManagedNativeBoundariesEvidence = (rawInput) => {
|
|
11
|
+
const parsed = managedNativeVerificationInputSchema.safeParse(rawInput);
|
|
12
|
+
if (!parsed.success)
|
|
13
|
+
return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
|
14
|
+
try {
|
|
15
|
+
const result = verifyManagedNativeBoundaries(parsed.data);
|
|
16
|
+
return ok(createManagedNativeVerificationEvidence(parsed.data, result));
|
|
17
|
+
}
|
|
18
|
+
catch (cause) {
|
|
19
|
+
return err(cause instanceof TypeError || cause instanceof z.ZodError
|
|
20
|
+
? new AnalysisInputError(OPERATION, { cause })
|
|
21
|
+
: new AnalysisProtocolError("Managed/native verification produced an invalid result", { cause }));
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const createManagedNativeVerificationEvidence = (input, result) => createEvidence(undefined, MANAGED_WORKFLOW_PROVIDER, {
|
|
25
|
+
predicateType: "rea.managed-native-verification/v1",
|
|
26
|
+
operation: OPERATION,
|
|
27
|
+
parameters: {
|
|
28
|
+
managed_boundaries_evidence_id: input.managed_boundaries.evidence_id,
|
|
29
|
+
native_evidence_ids: jsonValueSchema.parse(input.native_observations.map(({ evidence_id: id }) => id)),
|
|
30
|
+
limits: jsonValueSchema.parse(input.limits),
|
|
31
|
+
},
|
|
32
|
+
result: jsonValueSchema.parse(result),
|
|
33
|
+
rawResult: null,
|
|
34
|
+
confidence: "inferred",
|
|
35
|
+
authority: "analyst-inference",
|
|
36
|
+
environment: null,
|
|
37
|
+
limitations: result.limitations,
|
|
38
|
+
evidenceLinks: result.evidence_links,
|
|
39
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
|
|
3
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
4
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
|
+
import { importManagedReconstruction, managedReconstructionImportInputSchema, } from "../domain/managedReconstruction.js";
|
|
6
|
+
import { err, ok } from "../domain/result.js";
|
|
7
|
+
import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
8
|
+
const OPERATION = "import_managed_reconstruction";
|
|
9
|
+
/** Authenticate and import managed decompiler reconstruction as Evidence. */
|
|
10
|
+
export const importManagedReconstructionEvidence = (rawInput) => {
|
|
11
|
+
const parsed = managedReconstructionImportInputSchema.safeParse(rawInput);
|
|
12
|
+
if (!parsed.success)
|
|
13
|
+
return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
|
14
|
+
return importManagedReconstructionEvidenceValidated(parsed.data);
|
|
15
|
+
};
|
|
16
|
+
/** Import reconstruction from input parsed by a trusted adapter. */
|
|
17
|
+
export const importManagedReconstructionEvidenceValidated = (input) => {
|
|
18
|
+
try {
|
|
19
|
+
const result = importManagedReconstruction(input);
|
|
20
|
+
return ok(createManagedReconstructionEvidence(input, result));
|
|
21
|
+
}
|
|
22
|
+
catch (cause) {
|
|
23
|
+
return err(cause instanceof TypeError || cause instanceof z.ZodError
|
|
24
|
+
? new AnalysisInputError(OPERATION, { cause })
|
|
25
|
+
: new AnalysisProtocolError("Managed reconstruction import produced an invalid result", { cause }));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const createManagedReconstructionEvidence = (input, result) => createEvidence({
|
|
29
|
+
path: result.static_observation.artifact_path,
|
|
30
|
+
sha256: result.static_observation.artifact_sha256,
|
|
31
|
+
format: "pe",
|
|
32
|
+
}, MANAGED_WORKFLOW_PROVIDER, {
|
|
33
|
+
predicateType: "rea.managed-reconstruction-import/v1",
|
|
34
|
+
operation: OPERATION,
|
|
35
|
+
parameters: {
|
|
36
|
+
static_members_evidence_id: input.static_members.evidence_id,
|
|
37
|
+
decompiler: jsonValueSchema.parse(result.decompiler),
|
|
38
|
+
method_locks: jsonValueSchema.parse(input.methods.map(({ token, signature_sha256, normalized_il_sha256 }) => ({
|
|
39
|
+
token,
|
|
40
|
+
signature_sha256,
|
|
41
|
+
normalized_il_sha256,
|
|
42
|
+
}))),
|
|
43
|
+
notes: jsonValueSchema.parse(input.notes),
|
|
44
|
+
},
|
|
45
|
+
result: jsonValueSchema.parse(result),
|
|
46
|
+
rawResult: null,
|
|
47
|
+
confidence: "inferred",
|
|
48
|
+
authority: "analyst-inference",
|
|
49
|
+
environment: null,
|
|
50
|
+
limitations: result.limitations,
|
|
51
|
+
locations: [
|
|
52
|
+
{
|
|
53
|
+
kind: "artifact-path",
|
|
54
|
+
path: result.static_observation.artifact_path,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
evidenceLinks: result.evidence_links,
|
|
58
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisProtocolError, PermissionRequiredError, } from "../domain/errors.js";
|
|
2
|
+
import { createEvidence, parseEvidence, } from "../domain/evidence.js";
|
|
3
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
4
|
+
import { managedRuntimeCorrelationInputSchema, planManagedRuntimeCorrelation, } from "../domain/managedRuntimeCorrelation.js";
|
|
5
|
+
import { err, ok } from "../domain/result.js";
|
|
6
|
+
import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
7
|
+
import { digestJson } from "./JavaScriptReplayPlanning.js";
|
|
8
|
+
const OPERATION = "plan_managed_runtime_correlation";
|
|
9
|
+
/** Create a separately authorized, non-executing managed runtime plan Evidence. */
|
|
10
|
+
export const planManagedRuntimeCorrelationEvidence = async (dependencies, rawInput) => {
|
|
11
|
+
const parsed = managedRuntimeCorrelationInputSchema.safeParse(rawInput);
|
|
12
|
+
if (!parsed.success)
|
|
13
|
+
return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
|
14
|
+
return planManagedRuntimeCorrelationEvidenceValidated(dependencies, parsed.data);
|
|
15
|
+
};
|
|
16
|
+
/** Plan runtime correlation from input parsed by a trusted adapter. */
|
|
17
|
+
export const planManagedRuntimeCorrelationEvidenceValidated = async (dependencies, input) => {
|
|
18
|
+
if (!dependencies.policy.enabled)
|
|
19
|
+
return err(new AnalysisCapabilityUnavailableError(MANAGED_WORKFLOW_PROVIDER.id, OPERATION, "managed runtime correlation is disabled; configure exact roots and runtime executable before enabling it"));
|
|
20
|
+
if (dependencies.authority === undefined)
|
|
21
|
+
return err(new AnalysisCapabilityUnavailableError(MANAGED_WORKFLOW_PROVIDER.id, OPERATION, "managed runtime permission policy is not configured"));
|
|
22
|
+
let staticEvidence;
|
|
23
|
+
let artifactPath;
|
|
24
|
+
try {
|
|
25
|
+
staticEvidence = parseEvidence(input.static_members);
|
|
26
|
+
artifactPath = artifactPathFor(staticEvidence);
|
|
27
|
+
}
|
|
28
|
+
catch (cause) {
|
|
29
|
+
return err(new AnalysisInputError(OPERATION, { cause }));
|
|
30
|
+
}
|
|
31
|
+
const authorized = await dependencies.authority.explain({
|
|
32
|
+
capability: "managed_runtime",
|
|
33
|
+
roots: [artifactPath],
|
|
34
|
+
executables: [dependencies.policy.executablePath],
|
|
35
|
+
environment_names: [],
|
|
36
|
+
network: "none",
|
|
37
|
+
mount: false,
|
|
38
|
+
operation_identity: operationIdentity(input, staticEvidence),
|
|
39
|
+
}, "read", { restartRequired: true });
|
|
40
|
+
if (!authorized.ok)
|
|
41
|
+
return err(authorized.error instanceof PermissionRequiredError
|
|
42
|
+
? authorized.error
|
|
43
|
+
: new AnalysisProtocolError(authorized.error.message, {
|
|
44
|
+
cause: authorized.error,
|
|
45
|
+
}));
|
|
46
|
+
try {
|
|
47
|
+
const result = planManagedRuntimeCorrelation(input, dependencies.policy.executablePath, authorized.value.grant_id);
|
|
48
|
+
return ok(createEvidence({
|
|
49
|
+
path: result.static_observation.artifact_path,
|
|
50
|
+
sha256: result.static_observation.artifact_sha256,
|
|
51
|
+
format: "pe",
|
|
52
|
+
}, MANAGED_WORKFLOW_PROVIDER, {
|
|
53
|
+
predicateType: "rea.managed-runtime-correlation-plan/v1",
|
|
54
|
+
operation: OPERATION,
|
|
55
|
+
parameters: {
|
|
56
|
+
static_members_evidence_id: staticEvidence.evidence_id,
|
|
57
|
+
method: jsonValueSchema.parse(input.method),
|
|
58
|
+
requested_effect: input.requested_effect,
|
|
59
|
+
host: jsonValueSchema.parse(input.host),
|
|
60
|
+
bounds: jsonValueSchema.parse(input.bounds),
|
|
61
|
+
},
|
|
62
|
+
result: jsonValueSchema.parse(result),
|
|
63
|
+
rawResult: null,
|
|
64
|
+
confidence: "derived",
|
|
65
|
+
authority: "analyst-inference",
|
|
66
|
+
environment: null,
|
|
67
|
+
limitations: result.limitations,
|
|
68
|
+
locations: [
|
|
69
|
+
{
|
|
70
|
+
kind: "artifact-path",
|
|
71
|
+
path: result.static_observation.artifact_path,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
evidenceLinks: result.evidence_links,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
catch (cause) {
|
|
78
|
+
return err(cause instanceof TypeError
|
|
79
|
+
? new AnalysisInputError(OPERATION, { cause })
|
|
80
|
+
: new AnalysisProtocolError("Managed runtime correlation planning produced an invalid result", { cause }));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const artifactPathFor = (evidence) => {
|
|
84
|
+
const result = evidence.normalized_result;
|
|
85
|
+
if (typeof result === "object" &&
|
|
86
|
+
result !== null &&
|
|
87
|
+
"artifact" in result &&
|
|
88
|
+
typeof result.artifact === "object" &&
|
|
89
|
+
result.artifact !== null &&
|
|
90
|
+
"path" in result.artifact &&
|
|
91
|
+
typeof result.artifact.path === "string")
|
|
92
|
+
return result.artifact.path;
|
|
93
|
+
throw new AnalysisInputError(OPERATION, {
|
|
94
|
+
cause: new TypeError("Managed member Evidence does not expose an artifact path"),
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const operationIdentity = (input, evidence) => `${OPERATION}:${digestJson({
|
|
98
|
+
evidence_id: evidence.evidence_id,
|
|
99
|
+
method: input.method,
|
|
100
|
+
requested_effect: input.requested_effect,
|
|
101
|
+
host: input.host,
|
|
102
|
+
bounds: input.bounds,
|
|
103
|
+
})}`;
|
|
@@ -93,7 +93,7 @@ export class PermissionAuthority {
|
|
|
93
93
|
const decision = evaluatePermission(this.policy, canonical.value);
|
|
94
94
|
if (!decision.allowed)
|
|
95
95
|
return err(new PermissionRequiredError(canonical.value, decision.missing, ceilingFor(this.policy, canonical.value.capability), options.elicitationSupported ?? false, options.restartRequired ?? false));
|
|
96
|
-
return ok(decision);
|
|
96
|
+
return ok({ ...decision, request: canonical.value });
|
|
97
97
|
}
|
|
98
98
|
/** Add authority beneath the administrator ceiling. */
|
|
99
99
|
grant(grant) {
|
|
@@ -5,15 +5,19 @@ import { readProcessRunId } from "../process/ProcessOwnership.js";
|
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
6
|
const PROC_READ_CONCURRENCY = 64;
|
|
7
7
|
/** Prove that forkpty completed session setup and installed the run token. */
|
|
8
|
-
export const isInitializedPtyRoot = (options) =>
|
|
9
|
-
options.before.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
options.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
export const isInitializedPtyRoot = (options) => {
|
|
9
|
+
const sessionIdentityMatches = (options.before.session_id === options.rootPid &&
|
|
10
|
+
options.after.session_id === options.rootPid) ||
|
|
11
|
+
(options.before.session_id === null && options.after.session_id === null);
|
|
12
|
+
return (options.before.pid === options.rootPid &&
|
|
13
|
+
options.before.process_group_id === options.rootPid &&
|
|
14
|
+
sessionIdentityMatches &&
|
|
15
|
+
options.after.pid === options.rootPid &&
|
|
16
|
+
options.after.parent_pid === options.before.parent_pid &&
|
|
17
|
+
options.after.process_group_id === options.rootPid &&
|
|
18
|
+
options.after.startTime === options.before.startTime &&
|
|
19
|
+
options.observedRunId === options.expectedRunId);
|
|
20
|
+
};
|
|
17
21
|
const isExpectedProcReadFailure = (cause) => cause instanceof Error &&
|
|
18
22
|
"code" in cause &&
|
|
19
23
|
(cause.code === "ENOENT" ||
|
|
@@ -215,7 +219,7 @@ const readPsRows = async (signal) => {
|
|
|
215
219
|
pid: Number(match[1]),
|
|
216
220
|
parent_pid: Number(match[2]),
|
|
217
221
|
process_group_id: Number(match[3]),
|
|
218
|
-
session_id: Number(match[4]),
|
|
222
|
+
session_id: Number(match[4]) || null,
|
|
219
223
|
command: match[5] ?? "",
|
|
220
224
|
startTime: undefined,
|
|
221
225
|
}))
|
|
@@ -232,7 +236,7 @@ const inspectInitializedPtyRoot = async (rootPid, runId, signal) => {
|
|
|
232
236
|
const before = await readRootIdentity(rootPid, signal);
|
|
233
237
|
if (before === undefined ||
|
|
234
238
|
before.process_group_id !== rootPid ||
|
|
235
|
-
before.session_id !== rootPid)
|
|
239
|
+
(before.session_id !== rootPid && before.session_id !== null))
|
|
236
240
|
return undefined;
|
|
237
241
|
let observedRunId;
|
|
238
242
|
try {
|
|
@@ -3,6 +3,7 @@ import { HopperProvider } from "../hopper/HopperProvider.js";
|
|
|
3
3
|
import { GhidraProvider } from "../ghidra/GhidraProvider.js";
|
|
4
4
|
import { NativeMacOSProvider } from "../native/NativeMacOSProvider.js";
|
|
5
5
|
import { ArtifactProvider } from "../artifacts/ArtifactProvider.js";
|
|
6
|
+
import { ManagedStaticProvider } from "../dotnet/ManagedStaticProvider.js";
|
|
6
7
|
import { silentLogger } from "../logger.js";
|
|
7
8
|
import { AnalysisProviderRegistry } from "./AnalysisProviderRegistry.js";
|
|
8
9
|
import { SessionProviderRouter } from "./SessionProviderRouter.js";
|
|
@@ -17,5 +18,6 @@ export const createBinarySession = (config, logger = silentLogger) => {
|
|
|
17
18
|
return new BinarySession(SessionProviderRouter.selectable(new AnalysisProviderRegistry([hopper, ghidra], config.analysisProvider), [
|
|
18
19
|
new ArtifactProvider(config.artifactNativeMountEnabled, config.artifactIntegrityContinueEnabled),
|
|
19
20
|
new NativeMacOSProvider(),
|
|
21
|
+
new ManagedStaticProvider(),
|
|
20
22
|
]));
|
|
21
23
|
};
|
|
@@ -8,6 +8,7 @@ export class CdpCaptureEvents {
|
|
|
8
8
|
input;
|
|
9
9
|
allowedOrigins;
|
|
10
10
|
scripts = new Map();
|
|
11
|
+
executionContextFrames = new Map();
|
|
11
12
|
network = new Map();
|
|
12
13
|
allowedWebSockets = new Set();
|
|
13
14
|
console = [];
|
|
@@ -36,6 +37,7 @@ export class CdpCaptureEvents {
|
|
|
36
37
|
this.originViolation = false;
|
|
37
38
|
this.navigationDuringCapture = false;
|
|
38
39
|
this.scripts.clear();
|
|
40
|
+
this.executionContextFrames.clear();
|
|
39
41
|
this.network.clear();
|
|
40
42
|
this.allowedWebSockets.clear();
|
|
41
43
|
this.console.length = 0;
|
|
@@ -62,6 +64,15 @@ export class CdpCaptureEvents {
|
|
|
62
64
|
if (params === undefined)
|
|
63
65
|
return;
|
|
64
66
|
switch (event.method) {
|
|
67
|
+
case "Runtime.executionContextCreated":
|
|
68
|
+
this.#executionContext(params);
|
|
69
|
+
break;
|
|
70
|
+
case "Runtime.executionContextDestroyed":
|
|
71
|
+
this.#destroyExecutionContext(params);
|
|
72
|
+
break;
|
|
73
|
+
case "Runtime.executionContextsCleared":
|
|
74
|
+
this.executionContextFrames.clear();
|
|
75
|
+
break;
|
|
65
76
|
case "Debugger.scriptParsed":
|
|
66
77
|
this.#script(params);
|
|
67
78
|
break;
|
|
@@ -91,6 +102,37 @@ export class CdpCaptureEvents {
|
|
|
91
102
|
break;
|
|
92
103
|
}
|
|
93
104
|
}
|
|
105
|
+
/** Resolve a transient execution context to one already authorized frame. */
|
|
106
|
+
frameForScript(script, allowedFrameIds) {
|
|
107
|
+
if (script.executionContextKey === null)
|
|
108
|
+
return null;
|
|
109
|
+
const frameId = this.executionContextFrames.get(script.executionContextKey);
|
|
110
|
+
return frameId !== undefined && allowedFrameIds.has(frameId)
|
|
111
|
+
? frameId
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
#executionContext(params) {
|
|
115
|
+
const context = recordValue(params.context);
|
|
116
|
+
const identifier = numberValue(context?.id);
|
|
117
|
+
const frameId = stringValue(recordValue(context?.auxData)?.frameId);
|
|
118
|
+
if (identifier === undefined ||
|
|
119
|
+
!Number.isSafeInteger(identifier) ||
|
|
120
|
+
frameId === undefined ||
|
|
121
|
+
frameId.length > 256)
|
|
122
|
+
return;
|
|
123
|
+
const key = String(identifier);
|
|
124
|
+
if (this.executionContextFrames.size >= this.input.limits.max_scripts &&
|
|
125
|
+
!this.executionContextFrames.has(key)) {
|
|
126
|
+
this.completeness.truncate("scripts");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.executionContextFrames.set(key, frameId);
|
|
130
|
+
}
|
|
131
|
+
#destroyExecutionContext(params) {
|
|
132
|
+
const key = executionContextKey(params.executionContextId);
|
|
133
|
+
if (key !== null)
|
|
134
|
+
this.executionContextFrames.delete(key);
|
|
135
|
+
}
|
|
94
136
|
#script(params) {
|
|
95
137
|
const scriptId = stringValue(params.scriptId);
|
|
96
138
|
const rawUrl = stringValue(params.url) ?? "";
|
|
@@ -120,6 +162,7 @@ export class CdpCaptureEvents {
|
|
|
120
162
|
language: boundedText(params.scriptLanguage, 100),
|
|
121
163
|
sourceMapUrl: sourceMap.sanitized,
|
|
122
164
|
sourceMapRawUrl: sourceMap.raw,
|
|
165
|
+
executionContextKey: executionContextKey(params.executionContextId),
|
|
123
166
|
});
|
|
124
167
|
}
|
|
125
168
|
#sourceMap(value, scriptUrl) {
|
|
@@ -501,6 +544,12 @@ const integerOrNull = (value) => {
|
|
|
501
544
|
const number = numberValue(value);
|
|
502
545
|
return number === undefined ? null : Math.max(0, Math.trunc(number));
|
|
503
546
|
};
|
|
547
|
+
const executionContextKey = (value) => {
|
|
548
|
+
const identifier = numberValue(value);
|
|
549
|
+
return identifier !== undefined && Number.isSafeInteger(identifier)
|
|
550
|
+
? String(identifier)
|
|
551
|
+
: null;
|
|
552
|
+
};
|
|
504
553
|
const isJsonContentType = (headers) => {
|
|
505
554
|
if (headers === undefined)
|
|
506
555
|
return false;
|