rea-agents 2.0.0 → 2.2.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 (273) hide show
  1. package/README.md +103 -38
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/AndroidApplicationService.js +17 -0
  4. package/dist/application/AppleApplicationService.js +17 -0
  5. package/dist/application/ArtifactExtraction.js +1 -1
  6. package/dist/application/ArtifactInventory/classify.js +42 -0
  7. package/dist/application/ArtifactInventory/hash.js +43 -0
  8. package/dist/application/ArtifactInventory/reader.js +41 -0
  9. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  10. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  11. package/dist/application/ArtifactInventory/types.js +10 -0
  12. package/dist/application/ArtifactInventory.js +9 -351
  13. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  14. package/dist/application/BinarySession.js +47 -270
  15. package/dist/application/BinarySessionExecution.js +28 -0
  16. package/dist/application/BinarySessionOpen.js +39 -0
  17. package/dist/application/BinarySessionRecords.js +149 -0
  18. package/dist/application/BinarySessionStatus.js +75 -0
  19. package/dist/application/CapabilityInventory.js +24 -2
  20. package/dist/application/ClientRegistrationStatus.js +11 -4
  21. package/dist/application/CrossVersionInventory.js +8 -2
  22. package/dist/application/CrossVersionInvestigation.js +1 -23
  23. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  24. package/dist/application/DirectAnalysis.js +47 -44
  25. package/dist/application/Doctor.js +156 -238
  26. package/dist/application/DoctorDiagnostics.js +180 -0
  27. package/dist/application/ElectronBoundaryAnalysis.js +23 -7
  28. package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
  29. package/dist/application/EnhancedToolPagination.js +22 -0
  30. package/dist/application/EnhancedToolTypes.js +4 -0
  31. package/dist/application/EnhancedTools.js +20 -37
  32. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  33. package/dist/application/InventoryProjectionEvidence.js +41 -0
  34. package/dist/application/InvestigationProviders.js +12 -0
  35. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  36. package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
  37. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  38. package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
  39. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  40. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  41. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  42. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  43. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  44. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  45. package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
  46. package/dist/application/JavaScriptJsonModules.js +39 -0
  47. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  48. package/dist/application/JavaScriptReplayPermission.js +16 -0
  49. package/dist/application/JavaScriptReplayService.js +182 -156
  50. package/dist/application/LinuxHopper.js +10 -0
  51. package/dist/application/MacHopper.js +22 -11
  52. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  53. package/dist/application/PermissionAuthority.js +106 -63
  54. package/dist/application/ProcessCaptureCapability.js +1 -1
  55. package/dist/application/ProcessCapturePermission.js +13 -0
  56. package/dist/application/ProcessCli.js +2 -12
  57. package/dist/application/ProcessHarness.js +1 -1
  58. package/dist/application/ProcessPairedExperiment.js +72 -0
  59. package/dist/application/ProjectPermissionStore.js +48 -9
  60. package/dist/application/RealHopperAssertions.js +76 -0
  61. package/dist/application/ReconstructionCoverageService.js +69 -0
  62. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  63. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  64. package/dist/application/Setup.js +148 -260
  65. package/dist/application/SetupClientConfiguration.js +224 -0
  66. package/dist/application/SetupClients.js +24 -2
  67. package/dist/application/SetupPlan.js +124 -12
  68. package/dist/application/SetupSkill.js +54 -36
  69. package/dist/application/SupportedClients.js +1 -0
  70. package/dist/application/Uninstall.js +12 -3
  71. package/dist/application/Upgrade.js +16 -1
  72. package/dist/application/WindowsCapabilities.js +86 -0
  73. package/dist/artifacts/AsarArtifactReader.js +11 -0
  74. package/dist/browser/BrowserProcessStartup.js +88 -0
  75. package/dist/browser/CdpCaptureDocuments.js +12 -8
  76. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  77. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  78. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  79. package/dist/browser/CdpCaptureEventState.js +1 -0
  80. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  81. package/dist/browser/CdpCaptureEvents.js +29 -496
  82. package/dist/browser/CdpObservationSession.js +51 -8
  83. package/dist/browser/CdpPageCapture.js +12 -133
  84. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  85. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  86. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  87. package/dist/browser/PngVisualDiff.js +9 -2
  88. package/dist/catalogIdentity.js +4 -0
  89. package/dist/cli/artifactCommands.js +82 -0
  90. package/dist/cli/coreAnalysisCommands.js +232 -0
  91. package/dist/cli/managedCommands.js +397 -0
  92. package/dist/cli/managedProjectGraphCommand.js +24 -0
  93. package/dist/cli/options.js +9 -0
  94. package/dist/cli/setupCommands.js +113 -0
  95. package/dist/cli/types.js +1 -0
  96. package/dist/cli/utilityCommands.js +122 -0
  97. package/dist/cli.js +10 -768
  98. package/dist/cliApplicationCommands.js +118 -4
  99. package/dist/cliBrowserAdvancedCommands.js +73 -16
  100. package/dist/cliBrowserCommands.js +39 -115
  101. package/dist/cliCommandNames.js +4 -0
  102. package/dist/cliElectronCommands.js +33 -62
  103. package/dist/cliEvidenceCommands.js +13 -2
  104. package/dist/cliInvestigationCommands.js +53 -10
  105. package/dist/cliObservationOptions.js +137 -0
  106. package/dist/cliPolicyCommands.js +80 -46
  107. package/dist/cliSetup.js +306 -0
  108. package/dist/config/environment.js +107 -0
  109. package/dist/config/parseConfig.js +228 -0
  110. package/dist/config/parsers.js +68 -0
  111. package/dist/config/permissions.js +30 -0
  112. package/dist/config/types.js +1 -0
  113. package/dist/config.js +1 -375
  114. package/dist/contracts/applicationToolContracts.js +134 -0
  115. package/dist/contracts/electronToolContracts.js +51 -3
  116. package/dist/contracts/managedToolContracts.js +8 -3
  117. package/dist/contracts/managedWorkflowToolContracts.js +3 -3
  118. package/dist/contracts/providerSelection.js +2 -0
  119. package/dist/contracts/sessionStatusContract.js +26 -0
  120. package/dist/contracts/toolContractTypes.js +12 -1
  121. package/dist/contracts/toolContracts.js +5 -12
  122. package/dist/contracts/toolEffects.js +14 -0
  123. package/dist/contracts/toolOutputSchemaGroups.js +274 -0
  124. package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
  125. package/dist/contracts/toolOutputSchemas.js +2 -550
  126. package/dist/domain/analysisErrorPresentation.js +234 -0
  127. package/dist/domain/analysisErrorProjection.js +284 -0
  128. package/dist/domain/androidApplication.js +206 -0
  129. package/dist/domain/appleApplication.js +221 -0
  130. package/dist/domain/artifactComparison.js +34 -15
  131. package/dist/domain/binaryTarget.js +87 -37
  132. package/dist/domain/boundedCartesianProjection.js +15 -0
  133. package/dist/domain/browserObservation.js +1 -285
  134. package/dist/domain/browserObservationSchemas.js +286 -0
  135. package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
  136. package/dist/domain/errors.js +4 -486
  137. package/dist/domain/functionComparison.js +4 -165
  138. package/dist/domain/functionComparisonDimensions.js +164 -0
  139. package/dist/domain/javascriptApplicationVersionItems.js +18 -6
  140. package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
  141. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  142. package/dist/domain/javascriptFeatureTraversal.js +19 -7
  143. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  145. package/dist/domain/javascriptSemanticIr.js +30 -0
  146. package/dist/domain/javascriptSemanticProjection.js +366 -0
  147. package/dist/domain/javascriptSemanticState.js +40 -0
  148. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  149. package/dist/domain/javascriptSemanticValues.js +352 -0
  150. package/dist/domain/javascriptStaticAnalysis.js +5 -221
  151. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  152. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  153. package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
  154. package/dist/domain/knownPageCoverage.js +21 -0
  155. package/dist/domain/managedApplicationGraph.js +14 -364
  156. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  157. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  158. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  159. package/dist/domain/managedArtifact.js +16 -8
  160. package/dist/domain/managedMemberComparison.js +37 -391
  161. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  162. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  163. package/dist/domain/managedNativeVerification.js +27 -389
  164. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  165. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  166. package/dist/domain/managedReconstruction.js +82 -69
  167. package/dist/domain/managedRuntimeCorrelation.js +12 -3
  168. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  169. package/dist/domain/permissionPolicy.js +2 -0
  170. package/dist/domain/processComparison.js +19 -0
  171. package/dist/domain/processPairedExperiment.js +128 -0
  172. package/dist/domain/reconstructionCoverage.js +387 -0
  173. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  174. package/dist/domain/reconstructionVerificationSchemas.js +8 -0
  175. package/dist/domain/replayMachine.js +316 -0
  176. package/dist/domain/replayMachineRuntime.js +215 -0
  177. package/dist/domain/runtimeCharacterization.js +85 -0
  178. package/dist/domain/runtimeIdentification.js +210 -0
  179. package/dist/domain/webBundleAnalyzer.js +3 -409
  180. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  181. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  182. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  183. package/dist/dotnet/ManagedArtifactInspector.js +50 -29
  184. package/dist/dotnet/ManagedMemberInspector.js +51 -785
  185. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  186. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  187. package/dist/dotnet/ManagedMemberRows.js +120 -0
  188. package/dist/dotnet/ManagedMetadataInventory.js +42 -306
  189. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  190. package/dist/dotnet/ManagedMetadataLayout.js +48 -111
  191. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  192. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  193. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  194. package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
  195. package/dist/dotnet/ManagedPeReader.js +59 -28
  196. package/dist/evaluation/CodexAgentEval.js +132 -0
  197. package/dist/generatedPackageMetadata.js +2 -2
  198. package/dist/ghidra/GhidraClient.js +76 -91
  199. package/dist/ghidra/GhidraClientStartup.js +29 -0
  200. package/dist/ghidra/GhidraClientWire.js +34 -0
  201. package/dist/ghidra/GhidraDefaults.js +1 -1
  202. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  203. package/dist/ghidra/GhidraInstallation.js +20 -15
  204. package/dist/ghidra/GhidraLauncher.js +93 -29
  205. package/dist/ghidra/GhidraProvider.js +61 -161
  206. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  207. package/dist/ghidra/GhidraSessionValues.js +2 -0
  208. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  209. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  210. package/dist/ghidra/GhidraTransport.js +71 -0
  211. package/dist/identity.js +4 -2
  212. package/dist/main/messages.js +5 -0
  213. package/dist/main/reload.js +49 -0
  214. package/dist/main/shutdown.js +25 -0
  215. package/dist/main/startup.js +14 -0
  216. package/dist/main/state.js +26 -0
  217. package/dist/main/transport.js +61 -0
  218. package/dist/main/types.js +1 -0
  219. package/dist/main.js +35 -146
  220. package/dist/process/PrivateRuntimeRoot.js +3 -2
  221. package/dist/process/ProcessOwnership.js +35 -0
  222. package/dist/process/ProviderProcess.js +2 -0
  223. package/dist/replay/JavaScriptReplayWorker.js +64 -50
  224. package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
  225. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  226. package/dist/replay/ReplayOutcome.js +95 -0
  227. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  228. package/dist/server/ProcessCaptureElicitation.js +157 -0
  229. package/dist/server/createServer.js +124 -56
  230. package/dist/server/javascriptApplicationResult.js +85 -0
  231. package/dist/server/registerApplicationTools/characterization.js +57 -0
  232. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  233. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  234. package/dist/server/registerApplicationTools/coverage.js +84 -0
  235. package/dist/server/registerApplicationTools/helpers.js +42 -0
  236. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  237. package/dist/server/registerApplicationTools/types.js +1 -0
  238. package/dist/server/registerApplicationTools.js +10 -112
  239. package/dist/server/registerBrowserTools.js +59 -83
  240. package/dist/server/registerElectronTools.js +48 -49
  241. package/dist/server/registerEnhancedTools.js +34 -42
  242. package/dist/server/registerEvidenceResources.js +56 -0
  243. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  244. package/dist/server/registerInvestigationTools/types.js +1 -0
  245. package/dist/server/registerInvestigationTools.js +83 -116
  246. package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
  247. package/dist/server/registerManagedTools.js +18 -1
  248. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  249. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  250. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  251. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  252. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  253. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  254. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  255. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  256. package/dist/server/registerManagedWorkflowTools.js +10 -274
  257. package/dist/server/registerOfficialTools.js +73 -59
  258. package/dist/server/registerSessionRecordTools.js +137 -0
  259. package/dist/server/registerSessionStatusTool.js +97 -26
  260. package/dist/server/registerSessionTools.js +60 -164
  261. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  262. package/dist/server/toolRegistrationOptions.js +101 -3
  263. package/dist/server/toolResult.js +15 -4
  264. package/package.json +11 -11
  265. package/skills/reverse-engineer-anything/SKILL.md +76 -0
  266. package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
  267. package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
  268. package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
  269. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
  270. package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
  271. package/scripts/prepare-node-pty.mjs +0 -35
  272. package/scripts/rebuild-native.mjs +0 -22
  273. package/skills/rea-analysis/SKILL.md +0 -222
@@ -1,274 +1,19 @@
1
1
  import { managedNativeBoundaryInspectionSchema, } from "../domain/managedArtifact.js";
2
- import { metadataRowOffset, readManagedMetadataLayout, } from "./ManagedMetadataLayout.js";
3
- import { MetadataRowCursor, metadataToken, readMetadataString, } from "./ManagedMetadataHeaps.js";
4
- import { readManagedMetadataInventory, managedTableRowCounts, } from "./ManagedMetadataInventory.js";
2
+ import { readManagedMetadataInventory, } from "./ManagedMetadataInventory.js";
3
+ import { readManagedMetadataLayout, } from "./ManagedMetadataLayout.js";
5
4
  import { readManagedPeLayout, } from "./ManagedPeReader.js";
6
- import { ManagedReaderFailure, managedFailure, } from "./ManagedReaderFailure.js";
7
- const rowCursor = (bytes, layout, table, row) => {
8
- const descriptor = layout.table(table);
9
- const start = metadataRowOffset(layout, table, row);
10
- if (descriptor === undefined)
11
- throw managedFailure("invalid-row", `metadata.${String(table)}`, "Metadata table is absent", start);
12
- return new MetadataRowCursor(bytes, start, start + descriptor.rowSize, `metadata.${descriptor.name}`);
13
- };
14
- const codedToken = (raw, tagBits, tables) => {
15
- const tagMask = (1 << tagBits) - 1;
16
- const table = tables[raw & tagMask];
17
- const row = raw >> tagBits;
18
- if (table === undefined || row === 0)
19
- return null;
20
- return metadataToken(table, row);
21
- };
22
- const flagsHex = (value) => `0x${value.toString(16).padStart(4, "0")}`;
23
- const page = (items, offset, limit) => {
24
- const safeOffset = Math.min(offset, items.length);
25
- const selected = items.slice(safeOffset, safeOffset + limit);
26
- return {
27
- items: selected,
28
- offset,
29
- limit,
30
- total: items.length,
31
- returned: selected.length,
32
- dropped: Math.max(0, items.length - safeOffset - selected.length),
33
- complete: safeOffset === 0 && selected.length === items.length,
34
- };
35
- };
36
- const parseModuleRefs = (bytes, layout, maxBytes) => {
37
- const refs = [];
38
- const table = layout.table(26);
39
- for (let row = 1; row <= (table?.rowCount ?? 0); row += 1) {
40
- const cursor = rowCursor(bytes, layout, 26, row);
41
- refs.push({
42
- token: metadataToken(26, row),
43
- row_offset: cursor.start,
44
- name: readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes),
45
- });
46
- }
47
- return refs;
48
- };
49
- const parseFields = (bytes, layout, maxBytes) => {
50
- const fields = new Map();
51
- const table = layout.table(4);
52
- for (let row = 1; row <= (table?.rowCount ?? 0); row += 1) {
53
- const cursor = rowCursor(bytes, layout, 4, row);
54
- const flags = cursor.readUInt16();
55
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
56
- cursor.readIndex(layout.blobIndexSize);
57
- const token = metadataToken(4, row);
58
- fields.set(token, {
59
- token,
60
- rowOffset: cursor.start,
61
- kind: "field",
62
- name,
63
- flags,
64
- implFlags: null,
65
- rva: null,
66
- });
67
- }
68
- return fields;
69
- };
70
- const parseMethods = (bytes, layout, maxBytes) => {
71
- const methods = new Map();
72
- const table = layout.table(6);
73
- for (let row = 1; row <= (table?.rowCount ?? 0); row += 1) {
74
- const cursor = rowCursor(bytes, layout, 6, row);
75
- const rva = cursor.readUInt32();
76
- const implFlags = cursor.readUInt16();
77
- const flags = cursor.readUInt16();
78
- const name = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
79
- cursor.readIndex(layout.blobIndexSize);
80
- cursor.readIndex(layout.tableIndexSize(8));
81
- const token = metadataToken(6, row);
82
- methods.set(token, {
83
- token,
84
- rowOffset: cursor.start,
85
- kind: "method",
86
- name,
87
- flags,
88
- implFlags,
89
- rva,
90
- });
91
- }
92
- return methods;
93
- };
94
- const parseImplMaps = (bytes, layout, maxBytes, modules, members) => {
95
- const moduleNames = new Map(modules.map((module) => [module.token, module]));
96
- const imports = [];
97
- const table = layout.table(28);
98
- for (let row = 1; row <= (table?.rowCount ?? 0); row += 1) {
99
- const cursor = rowCursor(bytes, layout, 28, row);
100
- const mappingFlags = cursor.readUInt16();
101
- const memberToken = codedToken(cursor.readIndex(layout.codedIndexSize("MemberForwarded")), 1, [4, 6]);
102
- const importName = readMetadataString(bytes, layout, cursor.readIndex(layout.stringIndexSize), maxBytes);
103
- const importScopeRow = cursor.readIndex(layout.tableIndexSize(26));
104
- const importScopeToken = importScopeRow === 0 ? null : metadataToken(26, importScopeRow);
105
- const member = memberToken === null ? undefined : members.get(memberToken);
106
- imports.push({
107
- token: metadataToken(28, row),
108
- row_offset: cursor.start,
109
- mapping_flags: mappingFlags,
110
- mapping_flags_hex: flagsHex(mappingFlags),
111
- member_token: memberToken,
112
- member_kind: member?.kind ?? "unknown",
113
- member_name: member?.name ?? null,
114
- import_name: importName,
115
- import_scope_token: importScopeToken,
116
- import_scope_name: importScopeToken === null
117
- ? null
118
- : (moduleNames.get(importScopeToken)?.name ?? null),
119
- no_mangle: (mappingFlags & 0x0001) !== 0,
120
- char_set: charSet(mappingFlags),
121
- call_convention: callConvention(mappingFlags),
122
- supports_last_error: (mappingFlags & 0x0040) !== 0,
123
- best_fit: bestFit(mappingFlags),
124
- throw_on_unmappable_char: throwOnUnmappable(mappingFlags),
125
- verification: "managed-declaration-only",
126
- });
127
- }
128
- return imports;
129
- };
130
- const charSet = (flags) => {
131
- switch (flags & 0x0006) {
132
- case 0x0000:
133
- return "not-specified";
134
- case 0x0002:
135
- return "ansi";
136
- case 0x0004:
137
- return "unicode";
138
- case 0x0006:
139
- return "auto";
140
- default:
141
- return "unknown";
142
- }
143
- };
144
- const callConvention = (flags) => {
145
- switch (flags & 0x0700) {
146
- case 0x0000:
147
- return "not-specified";
148
- case 0x0100:
149
- return "winapi";
150
- case 0x0200:
151
- return "cdecl";
152
- case 0x0300:
153
- return "stdcall";
154
- case 0x0400:
155
- return "thiscall";
156
- case 0x0500:
157
- return "fastcall";
158
- default:
159
- return "unknown";
160
- }
161
- };
162
- const bestFit = (flags) => {
163
- switch (flags & 0x0030) {
164
- case 0x0000:
165
- return "assembly-default";
166
- case 0x0010:
167
- return "enabled";
168
- case 0x0020:
169
- return "disabled";
170
- default:
171
- return "unknown";
172
- }
173
- };
174
- const throwOnUnmappable = (flags) => {
175
- switch (flags & 0x3000) {
176
- case 0x0000:
177
- return "assembly-default";
178
- case 0x1000:
179
- return "enabled";
180
- case 0x2000:
181
- return "disabled";
182
- default:
183
- return "unknown";
184
- }
185
- };
186
- const nativeImplementations = (methods, pinvokeTokens) => {
187
- const implementations = [];
188
- for (const method of methods) {
189
- const implFlags = method.implFlags ?? 0;
190
- const codeType = codeTypeFor(implFlags);
191
- const managedKind = managedKindFor(implFlags);
192
- const pinvokeDeclared = pinvokeTokens.has(method.token) || (method.flags & 0x2000) !== 0;
193
- if (!pinvokeDeclared && codeType === "il" && managedKind === "managed")
194
- continue;
195
- implementations.push({
196
- token: method.token,
197
- row_offset: method.rowOffset,
198
- name: method.name,
199
- rva: method.rva ?? 0,
200
- flags: method.flags,
201
- impl_flags: implFlags,
202
- code_type: codeType,
203
- managed_kind: managedKind,
204
- pinvoke_declared: pinvokeDeclared,
205
- boundary_kind: boundaryKind(pinvokeDeclared, codeType, managedKind),
206
- body_interpretation: codeType === "il" && managedKind === "managed" && !pinvokeDeclared
207
- ? "managed-cil"
208
- : method.rva === 0
209
- ? "not-file-backed"
210
- : "native-or-runtime",
211
- });
212
- }
213
- return implementations;
214
- };
215
- const codeTypeFor = (implFlags) => {
216
- switch (implFlags & 0x0003) {
217
- case 0x0000:
218
- return "il";
219
- case 0x0001:
220
- return "native";
221
- case 0x0002:
222
- return "optil";
223
- case 0x0003:
224
- return "runtime";
225
- default:
226
- return "unknown";
227
- }
228
- };
229
- const managedKindFor = (implFlags) => {
230
- switch (implFlags & 0x0004) {
231
- case 0x0000:
232
- return "managed";
233
- case 0x0004:
234
- return "unmanaged";
235
- default:
236
- return "unknown";
237
- }
238
- };
239
- const boundaryKind = (pinvokeDeclared, codeType, managedKind) => {
240
- if (pinvokeDeclared)
241
- return "pinvoke";
242
- if (codeType === "native")
243
- return "native-body";
244
- if (codeType === "runtime")
245
- return "runtime-provided";
246
- if (managedKind === "unmanaged")
247
- return "unmanaged-method";
248
- return "mixed-or-unknown";
249
- };
250
- const cliNative = (pe) => {
251
- if (pe.cli === null)
252
- return {
253
- il_only: false,
254
- requires_32bit: false,
255
- strong_name_signed: false,
256
- native_entry_point: false,
257
- ready_to_run_signature: false,
258
- managed_native_header_rva: 0,
259
- managed_native_header_size: 0,
260
- };
261
- return {
262
- il_only: (pe.cli.flags & 0x0000_0001) !== 0,
263
- requires_32bit: (pe.cli.flags & 0x0000_0002) !== 0,
264
- strong_name_signed: (pe.cli.flags & 0x0000_0008) !== 0,
265
- native_entry_point: (pe.cli.flags & 0x0000_0010) !== 0,
266
- ready_to_run_signature: pe.cli.readyToRunSignature,
267
- managed_native_header_rva: pe.cli.managedNativeHeader.rva,
268
- managed_native_header_size: pe.cli.managedNativeHeader.size,
269
- };
270
- };
271
- const unavailable = (target, bytes, limits, issue) => managedNativeBoundaryInspectionSchema.parse({
5
+ import { ManagedReaderFailure } from "./ManagedReaderFailure.js";
6
+ import { buildNativeBoundaryInspection, cliNative, nativeImplementations, parseFields, parseImplMaps, parseMethods, parseModuleRefs, } from "./ManagedNativeBoundaryHelpers.js";
7
+ const emptyPage = () => ({
8
+ items: [],
9
+ offset: 0,
10
+ limit: 0,
11
+ total: 0,
12
+ returned: 0,
13
+ dropped: 0,
14
+ complete: true,
15
+ });
16
+ const emptyInspection = (target, bytes, classification, issues = []) => managedNativeBoundaryInspectionSchema.parse({
272
17
  schema_version: 1,
273
18
  artifact: {
274
19
  path: target.path,
@@ -277,7 +22,13 @@ const unavailable = (target, bytes, limits, issue) => managedNativeBoundaryInspe
277
22
  format: "pe",
278
23
  },
279
24
  module: null,
280
- metadata: { status: "absent", version: null, table_row_counts: {} },
25
+ metadata: {
26
+ status: classification === "malformed" || classification === "not-available"
27
+ ? "malformed"
28
+ : "absent",
29
+ version: null,
30
+ table_row_counts: {},
31
+ },
281
32
  identity_scope: {
282
33
  token_identity: "build-local",
283
34
  requires_artifact_sha256: target.sha256,
@@ -292,9 +43,9 @@ const unavailable = (target, bytes, limits, issue) => managedNativeBoundaryInspe
292
43
  managed_native_header_rva: 0,
293
44
  managed_native_header_size: 0,
294
45
  },
295
- module_refs: page([], limits.moduleRefOffset, limits.moduleRefLimit),
296
- pinvoke_imports: page([], limits.importOffset, limits.importLimit),
297
- native_implementations: page([], limits.implementationOffset, limits.implementationLimit),
46
+ module_refs: emptyPage(),
47
+ pinvoke_imports: emptyPage(),
48
+ native_implementations: emptyPage(),
298
49
  summary: {
299
50
  module_ref_count: 0,
300
51
  pinvoke_import_count: 0,
@@ -302,90 +53,91 @@ const unavailable = (target, bytes, limits, issue) => managedNativeBoundaryInspe
302
53
  ready_to_run: false,
303
54
  mixed_mode_or_native_header: false,
304
55
  },
305
- coverage: {
306
- state: "unavailable",
307
- issues: issue === null ? [] : [issue],
308
- },
56
+ coverage: { state: classification, issues },
309
57
  limitations: [
310
- "The PE has no admitted CLI metadata; managed/native boundary inspection is unavailable.",
58
+ "No CLI data was admitted; native boundary declarations are unavailable.",
59
+ "Static inspection does not load or execute target code, so native export resolution is not performed.",
311
60
  ],
312
61
  });
313
- /** Inspect PE/CLI managed/native boundary declarations without executing code. */
62
+ const readBoundaryInventory = (bytes, pe, limits) => {
63
+ const cli = pe.cli;
64
+ const metadataOffset = pe.rvaToOffset(cli.metadata.rva, cli.metadata.size, "cli.metadata");
65
+ const layout = readManagedMetadataLayout(bytes, metadataOffset, cli.metadata.size, limits.maxTableRows);
66
+ const resourceDirectory = {
67
+ offset: pe.rvaToOffset(cli.resources.rva, cli.resources.size, "cli.resources"),
68
+ size: cli.resources.size,
69
+ };
70
+ const inventory = readManagedMetadataInventory(bytes, layout, {
71
+ referenceOffset: 0,
72
+ referenceLimit: 0,
73
+ resourceOffset: 0,
74
+ resourceLimit: 0,
75
+ attributeOffset: 0,
76
+ attributeLimit: 0,
77
+ maxHeapItemBytes: limits.maxHeapItemBytes,
78
+ }, resourceDirectory);
79
+ return { layout, inventory };
80
+ };
81
+ const metadataLimitIssue = (cli, maxBytes) => ({
82
+ code: "limit-exceeded",
83
+ scope: "cli.metadata",
84
+ offset: cli.headerOffset + 8,
85
+ detail: `CLI metadata size exceeds max_metadata_bytes ${String(maxBytes)}`,
86
+ });
87
+ /** Inspect managed/native boundary declarations from PE metadata without execution. */
314
88
  export const inspectManagedNativeBoundariesBytes = (bytes, target, limits) => {
315
- const pe = readManagedPeLayout(bytes);
89
+ let pe;
90
+ try {
91
+ pe = readManagedPeLayout(bytes);
92
+ }
93
+ catch (cause) {
94
+ if (!(cause instanceof ManagedReaderFailure))
95
+ throw cause;
96
+ return emptyInspection(target, bytes, "malformed", [cause.issue]);
97
+ }
316
98
  if (pe.cli === null)
317
- return unavailable(target, bytes, limits, pe.cliIssue);
318
- const issues = [];
99
+ return emptyInspection(target, bytes, pe.cliDirectoryPresent ? "malformed" : "not-managed", pe.cliIssue === null ? [] : [pe.cliIssue]);
100
+ if (pe.cli.metadata.size > limits.maxMetadataBytes)
101
+ return emptyInspection(target, bytes, "malformed", [
102
+ metadataLimitIssue(pe.cli, limits.maxMetadataBytes),
103
+ ]);
104
+ let layout;
105
+ let inventory;
319
106
  try {
320
- const rootOffset = pe.rvaToOffset(pe.cli.metadata.rva, pe.cli.metadata.size, "cli.metadata");
321
- if (pe.cli.metadata.size > limits.maxMetadataBytes)
322
- throw managedFailure("limit-exceeded", "metadata.root", `CLI metadata size exceeds max_metadata_bytes ${String(limits.maxMetadataBytes)}`, rootOffset);
323
- const layout = readManagedMetadataLayout(bytes, rootOffset, pe.cli.metadata.size, limits.maxTableRows);
324
- const inventory = readManagedMetadataInventory(bytes, layout, {
325
- referenceOffset: 0,
326
- referenceLimit: 1,
327
- resourceOffset: 0,
328
- resourceLimit: 1,
329
- attributeOffset: 0,
330
- attributeLimit: 1,
331
- maxHeapItemBytes: limits.maxHeapItemBytes,
332
- }, null);
333
- issues.push(...inventory.issues);
334
- const moduleRefs = parseModuleRefs(bytes, layout, limits.maxHeapItemBytes);
335
- const fields = parseFields(bytes, layout, limits.maxHeapItemBytes);
336
- const methods = parseMethods(bytes, layout, limits.maxHeapItemBytes);
337
- const members = new Map([...fields, ...methods]);
338
- const imports = parseImplMaps(bytes, layout, limits.maxHeapItemBytes, moduleRefs, members);
339
- const implementations = nativeImplementations(methods.values(), new Set(imports
340
- .map(({ member_token: token }) => token)
341
- .filter((token) => token !== null)));
342
- const native = cliNative(pe);
343
- return managedNativeBoundaryInspectionSchema.parse({
344
- schema_version: 1,
345
- artifact: {
346
- path: target.path,
347
- sha256: target.sha256,
348
- byte_length: bytes.length,
349
- format: "pe",
350
- },
351
- module: inventory.module,
352
- metadata: {
353
- status: issues.length === 0 ? "complete" : "partial",
354
- version: layout.version,
355
- table_row_counts: managedTableRowCounts(layout),
356
- },
357
- identity_scope: {
358
- token_identity: "build-local",
359
- requires_artifact_sha256: target.sha256,
360
- requires_mvid: inventory.module?.mvid ?? null,
361
- },
362
- cli_native: native,
363
- module_refs: page(moduleRefs, limits.moduleRefOffset, limits.moduleRefLimit),
364
- pinvoke_imports: page(imports, limits.importOffset, limits.importLimit),
365
- native_implementations: page(implementations, limits.implementationOffset, limits.implementationLimit),
366
- summary: {
367
- module_ref_count: moduleRefs.length,
368
- pinvoke_import_count: imports.length,
369
- native_implementation_count: implementations.length,
370
- ready_to_run: native.ready_to_run_signature,
371
- mixed_mode_or_native_header: native.managed_native_header_rva !== 0 ||
372
- native.managed_native_header_size !== 0 ||
373
- native.native_entry_point,
374
- },
375
- coverage: {
376
- state: issues.length === 0 ? "complete" : "partial",
377
- issues,
378
- },
379
- limitations: [
380
- "P/Invoke rows prove managed import declarations only; this inspection does not verify that a native library, export, thunk, or provider-qualified function exists.",
381
- "Managed metadata tokens are build-local coordinates and are only meaningful with the reported artifact SHA-256 and MVID.",
382
- "ReadyToRun, NativeAOT, C++/CLI, and IL2CPP native semantics require separately selected native-provider evidence; this tool does not translate managed tokens into native addresses.",
383
- ],
384
- });
107
+ ({ layout, inventory } = readBoundaryInventory(bytes, pe, limits));
385
108
  }
386
109
  catch (cause) {
387
- if (cause instanceof ManagedReaderFailure)
388
- return unavailable(target, bytes, limits, cause.issue);
389
- throw cause;
110
+ if (!(cause instanceof ManagedReaderFailure))
111
+ throw cause;
112
+ return emptyInspection(target, bytes, "malformed", [cause.issue]);
390
113
  }
114
+ const moduleRefs = parseModuleRefs(bytes, layout, limits.maxHeapItemBytes);
115
+ const members = new Map([
116
+ ...parseFields(bytes, layout, limits.maxHeapItemBytes),
117
+ ...parseMethods(bytes, layout, limits.maxHeapItemBytes),
118
+ ]);
119
+ const imports = parseImplMaps({
120
+ bytes,
121
+ layout,
122
+ maxBytes: limits.maxHeapItemBytes,
123
+ modules: moduleRefs,
124
+ members,
125
+ });
126
+ const pinvokeTokens = new Set(imports
127
+ .map(({ member_token }) => member_token)
128
+ .filter((token) => token !== null));
129
+ const implementations = nativeImplementations(members.values(), pinvokeTokens);
130
+ return buildNativeBoundaryInspection({
131
+ target,
132
+ bytes,
133
+ limits,
134
+ pe,
135
+ layout,
136
+ inventory,
137
+ moduleRefs,
138
+ imports,
139
+ implementations,
140
+ native: cliNative(pe),
141
+ issues: [],
142
+ });
391
143
  };
@@ -27,7 +27,8 @@ const architectureFor = (machine) => {
27
27
  throw managedFailure("invalid-directory", "pe.machine", `Unsupported PE machine 0x${machine.toString(16).padStart(4, "0")}`);
28
28
  }
29
29
  };
30
- const mapRva = (bytes, sections, rva, size, scope) => {
30
+ const mapRva = (mapping) => {
31
+ const { bytes, sections, rva, size, scope } = mapping;
31
32
  if (rva === 0 && size === 0)
32
33
  return 0;
33
34
  for (const section of sections) {
@@ -55,7 +56,13 @@ const readDirectory = (bytes, offset) => {
55
56
  const readCliHeader = (bytes, sections, directory) => {
56
57
  if (directory.size < 72)
57
58
  throw managedFailure("invalid-cli-header", "cli.header", "CLI header is shorter than the required 72 bytes");
58
- const offset = mapRva(bytes, sections, directory.rva, 72, "cli.header");
59
+ const offset = mapRva({
60
+ bytes,
61
+ sections,
62
+ rva: directory.rva,
63
+ size: 72,
64
+ scope: "cli.header",
65
+ });
59
66
  const headerSize = bytes.readUInt32LE(offset);
60
67
  if (headerSize < 72 || headerSize > directory.size)
61
68
  throw managedFailure("invalid-cli-header", "cli.header", "CLI header size is outside its PE data directory", offset);
@@ -66,7 +73,13 @@ const readCliHeader = (bytes, sections, directory) => {
66
73
  const managedNativeHeader = readDirectory(bytes, offset + 64);
67
74
  let readyToRunSignature = false;
68
75
  if (managedNativeHeader.rva !== 0 && managedNativeHeader.size >= 4) {
69
- const nativeOffset = mapRva(bytes, sections, managedNativeHeader.rva, 4, "cli.managed-native-header");
76
+ const nativeOffset = mapRva({
77
+ bytes,
78
+ sections,
79
+ rva: managedNativeHeader.rva,
80
+ size: 4,
81
+ scope: "cli.managed-native-header",
82
+ });
70
83
  readyToRunSignature = bytes.readUInt32LE(nativeOffset) === 0x0052_5452;
71
84
  }
72
85
  return {
@@ -83,11 +96,7 @@ const readCliHeader = (bytes, sections, directory) => {
83
96
  readyToRunSignature,
84
97
  };
85
98
  };
86
- /** Parse the file-backed PE and CLI layout without loading target code. */
87
- export const readManagedPeLayout = (bytes) => {
88
- requireRange(bytes, 0, 64, "pe.dos-header");
89
- if (bytes[0] !== 0x4d || bytes[1] !== 0x5a)
90
- throw managedFailure("invalid-directory", "pe.dos-header", "Artifact does not start with an MZ header", 0);
99
+ const readCoffHeader = (bytes) => {
91
100
  const peOffset = bytes.readUInt32LE(0x3c);
92
101
  requireRange(bytes, peOffset, 24, "pe.coff-header");
93
102
  if (bytes.readUInt32LE(peOffset) !== 0x0000_4550)
@@ -99,22 +108,29 @@ export const readManagedPeLayout = (bytes) => {
99
108
  throw managedFailure("invalid-directory", "pe.sections", "PE section count is outside the admitted range", coff + 2);
100
109
  const optionalSize = bytes.readUInt16LE(coff + 16);
101
110
  const characteristics = bytes.readUInt16LE(coff + 18);
102
- const optionalOffset = coff + 20;
103
- requireRange(bytes, optionalOffset, optionalSize, "pe.optional-header");
104
- if (optionalSize < 96)
111
+ return { coff, machine, sectionCount, optionalSize, characteristics };
112
+ };
113
+ const readOptionalHeader = (bytes, coff) => {
114
+ const optionalOffset = coff.coff + 20;
115
+ requireRange(bytes, optionalOffset, coff.optionalSize, "pe.optional-header");
116
+ if (coff.optionalSize < 96)
105
117
  throw managedFailure("invalid-directory", "pe.optional-header", "PE optional header is too short", optionalOffset);
106
118
  const magic = bytes.readUInt16LE(optionalOffset);
107
119
  const optionalHeader = magic === 0x010b ? "pe32" : magic === 0x020b ? "pe32-plus" : undefined;
108
120
  if (optionalHeader === undefined)
109
121
  throw managedFailure("invalid-directory", "pe.optional-header", "PE optional header magic is unsupported", optionalOffset);
110
- const directoryCountOffset = optionalOffset + (optionalHeader === "pe32" ? 92 : 108);
111
- const directoryOffset = optionalOffset + (optionalHeader === "pe32" ? 96 : 112);
112
- requireRange(bytes, directoryCountOffset, 4, "pe.data-directories");
113
- const directoryCount = bytes.readUInt32LE(directoryCountOffset);
114
- const sectionOffset = add(optionalOffset, optionalSize, "pe.sections");
115
- requireRange(bytes, sectionOffset, sectionCount * 40, "pe.sections");
122
+ return {
123
+ optionalOffset,
124
+ optionalHeader,
125
+ directoryCountOffset: optionalOffset + (optionalHeader === "pe32" ? 92 : 108),
126
+ directoryOffset: optionalOffset + (optionalHeader === "pe32" ? 96 : 112),
127
+ };
128
+ };
129
+ const readSections = (bytes, coff, optional) => {
130
+ const sectionOffset = add(optional.optionalOffset, coff.optionalSize, "pe.sections");
131
+ requireRange(bytes, sectionOffset, coff.sectionCount * 40, "pe.sections");
116
132
  const sections = [];
117
- for (let index = 0; index < sectionCount; index += 1) {
133
+ for (let index = 0; index < coff.sectionCount; index += 1) {
118
134
  const offset = sectionOffset + index * 40;
119
135
  const section = {
120
136
  virtualSize: bytes.readUInt32LE(offset + 8),
@@ -126,10 +142,25 @@ export const readManagedPeLayout = (bytes) => {
126
142
  requireRange(bytes, section.rawOffset, section.rawSize, "pe.section-data");
127
143
  sections.push(section);
128
144
  }
129
- const cliDirectory = directoryCount <= 14 ||
130
- optionalSize < directoryOffset - optionalOffset + 120
131
- ? { rva: 0, size: 0 }
132
- : readDirectory(bytes, directoryOffset + 14 * 8);
145
+ return sections;
146
+ };
147
+ const readCliDirectory = (bytes, coff, optional) => {
148
+ requireRange(bytes, optional.directoryCountOffset, 4, "pe.data-directories");
149
+ const directoryCount = bytes.readUInt32LE(optional.directoryCountOffset);
150
+ if (directoryCount <= 14 ||
151
+ coff.optionalSize < optional.directoryOffset - optional.optionalOffset + 120)
152
+ return { rva: 0, size: 0 };
153
+ return readDirectory(bytes, optional.directoryOffset + 14 * 8);
154
+ };
155
+ /** Parse the file-backed PE and CLI layout without loading target code. */
156
+ export const readManagedPeLayout = (bytes) => {
157
+ requireRange(bytes, 0, 64, "pe.dos-header");
158
+ if (bytes[0] !== 0x4d || bytes[1] !== 0x5a)
159
+ throw managedFailure("invalid-directory", "pe.dos-header", "Artifact does not start with an MZ header", 0);
160
+ const coff = readCoffHeader(bytes);
161
+ const optional = readOptionalHeader(bytes, coff);
162
+ const sections = readSections(bytes, coff, optional);
163
+ const cliDirectory = readCliDirectory(bytes, coff, optional);
133
164
  const cliDirectoryPresent = cliDirectory.rva !== 0 || cliDirectory.size !== 0;
134
165
  let cli = null;
135
166
  let cliIssue = null;
@@ -143,15 +174,15 @@ export const readManagedPeLayout = (bytes) => {
143
174
  cliIssue = cause.issue;
144
175
  }
145
176
  return {
146
- machine,
147
- architecture: architectureFor(machine),
148
- optionalHeader,
149
- sectionCount,
150
- characteristics,
177
+ machine: coff.machine,
178
+ architecture: architectureFor(coff.machine),
179
+ optionalHeader: optional.optionalHeader,
180
+ sectionCount: coff.sectionCount,
181
+ characteristics: coff.characteristics,
151
182
  sections,
152
183
  cli,
153
184
  cliDirectoryPresent,
154
185
  cliIssue,
155
- rvaToOffset: (rva, size, scope) => mapRva(bytes, sections, rva, size, scope),
186
+ rvaToOffset: (rva, size, scope) => mapRva({ bytes, sections, rva, size, scope }),
156
187
  };
157
188
  };