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.
Files changed (156) hide show
  1. package/README.md +38 -31
  2. package/dist/application/CapabilityInventory.js +18 -0
  3. package/dist/application/CrossVersionInvestigation.js +10 -6
  4. package/dist/application/Doctor.js +56 -6
  5. package/dist/application/ElectronBoundaryAnalysis.js +96 -0
  6. package/dist/application/ElectronBoundaryGraph.js +9 -0
  7. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  8. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  9. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  10. package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
  11. package/dist/application/EnhancedTools.js +38 -13
  12. package/dist/application/InvestigationProviders.js +30 -0
  13. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  14. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  15. package/dist/application/JavaScriptApplicationService.js +74 -0
  16. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  17. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  18. package/dist/application/JavaScriptArtifactAnalysis.js +7 -1
  19. package/dist/application/JavaScriptArtifactGraphBuilder.js +59 -16
  20. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  21. package/dist/application/JavaScriptArtifactReconstruction.js +3 -0
  22. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  23. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  24. package/dist/application/JavaScriptReplayService.js +266 -0
  25. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  26. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  27. package/dist/application/ManagedApplicationGraphService.js +55 -0
  28. package/dist/application/ManagedMemberComparisonService.js +122 -0
  29. package/dist/application/ManagedNativeVerificationService.js +39 -0
  30. package/dist/application/ManagedReconstructionService.js +58 -0
  31. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  32. package/dist/application/PermissionAuthority.js +1 -1
  33. package/dist/application/ProcessSampling.js +15 -11
  34. package/dist/application/ProjectPermissionStore.js +1 -0
  35. package/dist/application/runtime.js +2 -0
  36. package/dist/browser/CdpCaptureEvents.js +49 -0
  37. package/dist/browser/CdpElectronInspection.js +106 -162
  38. package/dist/browser/CdpElectronProvider.js +5 -1
  39. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  40. package/dist/browser/CdpElectronScripts.js +94 -0
  41. package/dist/browser/CdpElectronWorkers.js +56 -0
  42. package/dist/browser/CdpPageCapture.js +8 -4
  43. package/dist/catalogIdentity.js +4 -1
  44. package/dist/cli.js +388 -0
  45. package/dist/cliApplicationCommands.js +62 -0
  46. package/dist/cliCommandNames.js +13 -0
  47. package/dist/cliElectronCommands.js +103 -1
  48. package/dist/cliJsonInput.js +54 -0
  49. package/dist/config.js +83 -0
  50. package/dist/contracts/applicationToolContracts.js +91 -0
  51. package/dist/contracts/artifactToolContracts.js +5 -9
  52. package/dist/contracts/browserToolContracts.js +14 -62
  53. package/dist/contracts/electronToolContracts.js +45 -19
  54. package/dist/contracts/errorSchemas.js +1 -0
  55. package/dist/contracts/investigationExamples.js +0 -6
  56. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  57. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  58. package/dist/contracts/managedToolContracts.js +153 -0
  59. package/dist/contracts/managedWorkflowExamples.js +346 -0
  60. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  61. package/dist/contracts/nativeToolContracts.js +2 -6
  62. package/dist/contracts/promptContracts.js +18 -2
  63. package/dist/contracts/toolContractExamples.js +10 -25
  64. package/dist/contracts/toolContracts.js +47 -45
  65. package/dist/contracts/toolEffects.js +160 -0
  66. package/dist/contracts/toolOutputSchemas.js +46 -31
  67. package/dist/doctorRuntime.js +42 -1
  68. package/dist/domain/artifactComparison.js +3 -4
  69. package/dist/domain/browserObservation.js +3 -0
  70. package/dist/domain/bundleComparison.js +4 -4
  71. package/dist/domain/electronObservation.js +13 -0
  72. package/dist/domain/electronStaticAnalysis.js +9 -0
  73. package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
  74. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  75. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  76. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  77. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  78. package/dist/domain/errors.js +67 -1
  79. package/dist/domain/functionComparisonSchemas.js +3 -8
  80. package/dist/domain/inputIssueProjection.js +52 -0
  81. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  82. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  83. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  84. package/dist/domain/javascriptApplicationGraph.js +2 -1
  85. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  86. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  87. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  88. package/dist/domain/javascriptApplicationVersionItems.js +221 -0
  89. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  90. package/dist/domain/javascriptFeatureSeed.js +140 -0
  91. package/dist/domain/javascriptFeatureTrace.js +232 -0
  92. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  93. package/dist/domain/javascriptFeatureTraversal.js +88 -0
  94. package/dist/domain/javascriptNativeHandoff.js +85 -0
  95. package/dist/domain/javascriptReplay.js +361 -0
  96. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  97. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  98. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  99. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  100. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  101. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  102. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  103. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  104. package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
  105. package/dist/domain/javascriptStaticAnalysis.js +31 -43
  106. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  107. package/dist/domain/javascriptStaticAnalysisHelpers.js +10 -0
  108. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  109. package/dist/domain/managedApplicationGraph.js +556 -0
  110. package/dist/domain/managedArtifact.js +444 -0
  111. package/dist/domain/managedMemberComparison.js +565 -0
  112. package/dist/domain/managedNativeVerification.js +408 -0
  113. package/dist/domain/managedReconstruction.js +183 -0
  114. package/dist/domain/managedRuntimeCorrelation.js +175 -0
  115. package/dist/domain/reconstructionVerificationSchemas.js +1 -3
  116. package/dist/dotnet/ManagedArtifactInspector.js +318 -0
  117. package/dist/dotnet/ManagedMemberInspector.js +887 -0
  118. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  119. package/dist/dotnet/ManagedMetadataInventory.js +368 -0
  120. package/dist/dotnet/ManagedMetadataLayout.js +322 -0
  121. package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
  122. package/dist/dotnet/ManagedPeReader.js +157 -0
  123. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  124. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  125. package/dist/generatedPackageMetadata.js +2 -2
  126. package/dist/ghidra/GhidraProvider.js +6 -0
  127. package/dist/main.js +14 -0
  128. package/dist/replay/JavaScriptReplayWorker.js +286 -0
  129. package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
  130. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  131. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  132. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  133. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  134. package/dist/server/createServer.js +52 -0
  135. package/dist/server/registerApplicationTools.js +115 -0
  136. package/dist/server/registerArtifactComparisonTool.js +16 -9
  137. package/dist/server/registerBrowserTools.js +33 -8
  138. package/dist/server/registerBundleComparisonTool.js +17 -20
  139. package/dist/server/registerElectronTools.js +45 -3
  140. package/dist/server/registerEnhancedTools.js +58 -13
  141. package/dist/server/registerEvidenceTools.js +5 -1
  142. package/dist/server/registerFunctionComparisonTool.js +14 -7
  143. package/dist/server/registerInvestigationTools.js +21 -17
  144. package/dist/server/registerManagedTools.js +6 -0
  145. package/dist/server/registerManagedWorkflowTools.js +277 -0
  146. package/dist/server/registerOfficialTools.js +8 -8
  147. package/dist/server/registerProcessComparisonTool.js +25 -47
  148. package/dist/server/registerSessionStatusTool.js +7 -7
  149. package/dist/server/registerSessionTools.js +51 -86
  150. package/dist/server/sessionEvidence.js +14 -19
  151. package/dist/server/toolInputValidation.js +77 -0
  152. package/dist/server/toolRegistrationOptions.js +79 -2
  153. package/dist/server/toolResult.js +25 -17
  154. package/package.json +12 -4
  155. package/scripts/rea.mjs +1 -1
  156. 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) => options.before.pid === options.rootPid &&
9
- options.before.process_group_id === options.rootPid &&
10
- options.before.session_id === options.rootPid &&
11
- options.after.pid === options.rootPid &&
12
- options.after.parent_pid === options.before.parent_pid &&
13
- options.after.process_group_id === options.rootPid &&
14
- options.after.session_id === options.rootPid &&
15
- options.after.startTime === options.before.startTime &&
16
- options.observedRunId === options.expectedRunId;
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 {
@@ -21,6 +21,7 @@ const grantSchema = z.object({
21
21
  "artifact_extract",
22
22
  "native_mount",
23
23
  "reference_read",
24
+ "javascript_replay",
24
25
  ]),
25
26
  roots: z.array(z.string()),
26
27
  executables: z.array(z.string()),
@@ -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;