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
@@ -0,0 +1,209 @@
1
+ import * as t from "@babel/types";
2
+ import { collectJavaScriptExports, fingerprintJavaScriptAst, } from "./javascriptAstFingerprint.js";
3
+ import { addBoundedFinding } from "./javascriptStaticAnalysisFindings.js";
4
+ import { argumentValue, calleeName, chunkRuntime, compareCodePoints, factoryRequireName, moduleFactory, modulePropertyName, range, registrationKey, sha256Text, sourceSlice, staticArrayValues, } from "./javascriptStaticAnalysisHelpers.js";
5
+ /** Inspect a bundler registration call and recover its module table. */
6
+ export const inspectBundlerRegistration = (source, call, accumulator, limits) => {
7
+ const runtime = chunkRuntime(call);
8
+ const entry = call.arguments[0];
9
+ if (runtime === undefined || !t.isArrayExpression(entry))
10
+ return;
11
+ const chunkIds = entry.elements[0];
12
+ const table = entry.elements[1];
13
+ const runtimeValue = runtimeMetadata(entry.elements[2], limits.maxFindings);
14
+ if (!t.isArrayExpression(chunkIds) || !t.isObjectExpression(table))
15
+ return;
16
+ const recovered = recoverBundlerModules(source, table, accumulator, limits);
17
+ const chunkKeys = staticArrayValues(chunkIds, Math.min(256, limits.maxFindings));
18
+ if (chunkKeys.omitted > 0) {
19
+ accumulator.droppedFindings += chunkKeys.omitted;
20
+ accumulator.structuralTruncation = true;
21
+ }
22
+ accumulator.unknownFindings += chunkKeys.unknown;
23
+ if (runtimeValue.omittedEntryModuleKeys > 0 ||
24
+ runtimeValue.omittedAsyncChunkKeys > 0 ||
25
+ recovered.omittedAsyncChunkKeys > 0) {
26
+ accumulator.droppedFindings +=
27
+ runtimeValue.omittedEntryModuleKeys +
28
+ runtimeValue.omittedAsyncChunkKeys +
29
+ recovered.omittedAsyncChunkKeys;
30
+ accumulator.structuralTruncation = true;
31
+ }
32
+ accumulator.unknownFindings +=
33
+ runtimeValue.unknownEntryModuleKeys +
34
+ runtimeValue.unknownAsyncChunkKeys +
35
+ recovered.unknownAsyncChunkKeys;
36
+ const asyncChunkKeys = boundedUniqueValues([...runtimeValue.asyncChunkKeys, ...recovered.asyncChunkKeys], Math.min(256, limits.maxFindings));
37
+ if (asyncChunkKeys.omitted > 0) {
38
+ accumulator.droppedFindings += asyncChunkKeys.omitted;
39
+ accumulator.structuralTruncation = true;
40
+ }
41
+ const registration = {
42
+ bundler: runtime.toLowerCase().includes("rspack")
43
+ ? "rspack"
44
+ : "webpack",
45
+ runtime,
46
+ chunk_keys: chunkKeys.values,
47
+ omitted_chunk_keys: chunkKeys.omitted,
48
+ unknown_chunk_keys: chunkKeys.unknown,
49
+ runtime_require_name: runtimeValue.requireName,
50
+ runtime_module_cache_status: bundlerModuleCacheStatus(source),
51
+ entry_module_keys: runtimeValue.entryModuleKeys,
52
+ omitted_entry_module_keys: runtimeValue.omittedEntryModuleKeys,
53
+ unknown_entry_module_keys: runtimeValue.unknownEntryModuleKeys,
54
+ async_chunk_keys: asyncChunkKeys.values,
55
+ omitted_async_chunk_keys: runtimeValue.omittedAsyncChunkKeys +
56
+ recovered.omittedAsyncChunkKeys +
57
+ asyncChunkKeys.omitted,
58
+ unknown_async_chunk_keys: runtimeValue.unknownAsyncChunkKeys + recovered.unknownAsyncChunkKeys,
59
+ modules: recovered.modules.sort((left, right) => compareCodePoints(left.module_key, right.module_key)),
60
+ location: range(call),
61
+ };
62
+ addBoundedFinding(accumulator, `registration\0${registrationKey(registration)}`, limits.maxFindings, () => accumulator.registrations.push(registration));
63
+ };
64
+ const recoverBundlerModules = (source, table, accumulator, limits) => {
65
+ const modules = [];
66
+ const asyncChunkKeys = [];
67
+ let omittedAsyncChunkKeys = 0;
68
+ let unknownAsyncChunkKeys = 0;
69
+ for (const property of table.properties) {
70
+ const recovered = recoverBundlerModule(source, property, accumulator, limits);
71
+ if (recovered === null)
72
+ continue;
73
+ modules.push(recovered.module);
74
+ asyncChunkKeys.push(...recovered.asyncChunkKeys);
75
+ omittedAsyncChunkKeys += recovered.omittedAsyncChunkKeys;
76
+ unknownAsyncChunkKeys += recovered.unknownAsyncChunkKeys;
77
+ }
78
+ return {
79
+ modules,
80
+ asyncChunkKeys,
81
+ omittedAsyncChunkKeys,
82
+ unknownAsyncChunkKeys,
83
+ };
84
+ };
85
+ const recoverBundlerModule = (source, property, accumulator, limits) => {
86
+ const factory = moduleFactory(property);
87
+ if (factory === undefined)
88
+ return null;
89
+ if (accumulator.moduleCount >= limits.maxModules) {
90
+ accumulator.droppedFindings += 1;
91
+ return null;
92
+ }
93
+ accumulator.moduleCount += 1;
94
+ const key = modulePropertyName(property);
95
+ if (key.startsWith("[computed@") || key.startsWith("[unknown@"))
96
+ accumulator.unknownFindings += 1;
97
+ const fingerprint = fingerprintJavaScriptAst(factory, Math.min(limits.maxAstNodes, 100_000));
98
+ const exportsValue = collectJavaScriptExports(factory, 256);
99
+ const requireName = factoryRequireName(factory);
100
+ const asyncChunks = collectBundlerAsyncChunkKeys(factory, requireName, limits.maxFindings);
101
+ if (fingerprint.truncated || exportsValue.truncated) {
102
+ accumulator.droppedFindings += 1;
103
+ accumulator.structuralTruncation = true;
104
+ }
105
+ if (typeof factory.start === "number" && typeof factory.end === "number")
106
+ accumulator.modules.push({
107
+ start: factory.start,
108
+ end: factory.end,
109
+ key,
110
+ requireName,
111
+ });
112
+ return {
113
+ module: {
114
+ module_key: key,
115
+ factory_require_name: requireName,
116
+ source_sha256: sha256Text(sourceSlice(source, factory)),
117
+ structural_fingerprint_sha256: fingerprint.truncated
118
+ ? null
119
+ : fingerprint.sha256,
120
+ structural_fingerprint_algorithm: fingerprint.truncated
121
+ ? null
122
+ : "babel-ast-v1",
123
+ structural_fingerprint_status: fingerprint.truncated
124
+ ? "truncated"
125
+ : "complete",
126
+ exports: exportsValue.values,
127
+ exports_truncated: exportsValue.truncated,
128
+ location: range(factory),
129
+ },
130
+ asyncChunkKeys: asyncChunks.values,
131
+ omittedAsyncChunkKeys: asyncChunks.omitted,
132
+ unknownAsyncChunkKeys: asyncChunks.unknown,
133
+ };
134
+ };
135
+ const runtimeMetadata = (node, maximum) => {
136
+ if (!isBundlerFunction(node))
137
+ return {
138
+ requireName: null,
139
+ entryModuleKeys: [],
140
+ omittedEntryModuleKeys: 0,
141
+ unknownEntryModuleKeys: node === null || node === undefined ? 0 : 1,
142
+ asyncChunkKeys: [],
143
+ omittedAsyncChunkKeys: 0,
144
+ unknownAsyncChunkKeys: 0,
145
+ };
146
+ const parameter = node.params[0];
147
+ const requireName = t.isIdentifier(parameter)
148
+ ? parameter.name.slice(0, 4_096)
149
+ : null;
150
+ if (requireName === null)
151
+ return {
152
+ requireName,
153
+ entryModuleKeys: [],
154
+ omittedEntryModuleKeys: 0,
155
+ unknownEntryModuleKeys: 1,
156
+ asyncChunkKeys: [],
157
+ omittedAsyncChunkKeys: 0,
158
+ unknownAsyncChunkKeys: 0,
159
+ };
160
+ const entries = collectBundlerEntryModuleKeys(node, requireName, maximum);
161
+ const asyncChunks = collectBundlerAsyncChunkKeys(node, requireName, maximum);
162
+ return {
163
+ requireName,
164
+ entryModuleKeys: entries.values,
165
+ omittedEntryModuleKeys: entries.omitted,
166
+ unknownEntryModuleKeys: entries.unknown,
167
+ asyncChunkKeys: asyncChunks.values,
168
+ omittedAsyncChunkKeys: asyncChunks.omitted,
169
+ unknownAsyncChunkKeys: asyncChunks.unknown,
170
+ };
171
+ };
172
+ const collectBundlerEntryModuleKeys = (factory, requireName, maximum) => collectBundlerCallArgumentValues(factory, requireName, maximum);
173
+ const collectBundlerAsyncChunkKeys = (factory, requireName, maximum) => requireName === null
174
+ ? { values: [], omitted: 0, unknown: 0 }
175
+ : collectBundlerCallArgumentValues(factory, `${requireName}.e`, maximum);
176
+ const collectBundlerCallArgumentValues = (factory, callee, maximum) => {
177
+ const values = [];
178
+ let unknown = 0;
179
+ t.traverseFast(factory, (node) => {
180
+ if (!t.isCallExpression(node) && !t.isNewExpression(node))
181
+ return undefined;
182
+ if (calleeName(node.callee) !== callee)
183
+ return undefined;
184
+ const value = argumentValue(node.arguments[0]);
185
+ if (value === undefined)
186
+ unknown += 1;
187
+ else
188
+ values.push(value);
189
+ return undefined;
190
+ });
191
+ return boundedUniqueValues(values, Math.min(256, maximum), unknown);
192
+ };
193
+ const isBundlerFunction = (node) => t.isFunctionExpression(node) ||
194
+ t.isArrowFunctionExpression(node) ||
195
+ t.isObjectMethod(node);
196
+ const boundedUniqueValues = (values, maximum, unknown = 0) => {
197
+ const bounded = [
198
+ ...new Set(values.map((value) => value.slice(0, 4_096))),
199
+ ].sort(compareCodePoints);
200
+ const retained = bounded.slice(0, Math.max(0, maximum));
201
+ return {
202
+ values: retained,
203
+ omitted: Math.max(0, bounded.length - retained.length),
204
+ unknown,
205
+ };
206
+ };
207
+ const bundlerModuleCacheStatus = (source) => /\b(?:__webpack_module_cache__|__rspack_module_cache__|installedModules)\b/u.test(source)
208
+ ? "observed"
209
+ : "not-observed";
@@ -0,0 +1,180 @@
1
+ import * as t from "@babel/types";
2
+ import { addBoundedFinding, addLocatedFinding, moduleAtOffset, } from "./javascriptStaticAnalysisFindings.js";
3
+ import { STATIC_ROUTE_CALL_NAMES, argumentValue, calleeName, endpointArgument as endpointArgumentHelper, prefixedArgument, propertyName, range, rangeForOffsets, sanitizeCandidate, sourceSlice, staticPath, staticPathResolutionContext, storageKind, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
4
+ /** Inspect one call or new expression for references, endpoints, storage, and roles. */
5
+ export const inspectCall = (node, context) => {
6
+ const { accumulator } = context;
7
+ const name = calleeName(node.callee);
8
+ const first = stringValue(node.arguments[0]);
9
+ const module = moduleAtOffset(node.start, context.accumulator.modules);
10
+ const moduleRequireName = module?.requireName ?? null;
11
+ const requireCall = requireCallSpecifier(node, name, moduleRequireName);
12
+ if (requireCall !== null)
13
+ addReference(context, {
14
+ node,
15
+ kind: "require",
16
+ specifier: requireCall.specifier,
17
+ });
18
+ const chunkLoad = chunkLoadSpecifier(node, name, moduleRequireName);
19
+ if (chunkLoad !== null)
20
+ addReference(context, {
21
+ node,
22
+ kind: "dynamic-import",
23
+ specifier: chunkLoad.specifier,
24
+ });
25
+ if (name === "Worker" || name.endsWith(".Worker"))
26
+ addReference(context, { node, kind: "worker", specifier: first });
27
+ if (name.endsWith("serviceWorker.register"))
28
+ addReference(context, { node, kind: "service-worker", specifier: first });
29
+ inspectEndpointCall(node, name, first, context);
30
+ inspectStorageCall(node, name, first, context);
31
+ if (name.endsWith("loadFile") && first !== undefined)
32
+ addLocatedFinding(context, {
33
+ collection: accumulator.roles,
34
+ key: `role\0renderer\0${first}`,
35
+ node,
36
+ value: {
37
+ role: "renderer",
38
+ path: first,
39
+ resolution_context: "filesystem-expression",
40
+ mechanism: `call:${name}`,
41
+ module_key: null,
42
+ location: range(node),
43
+ },
44
+ });
45
+ if (name.endsWith("loadURL") && first !== undefined)
46
+ addLocatedFinding(context, {
47
+ collection: accumulator.roles,
48
+ key: `role\0renderer\0${first}`,
49
+ node,
50
+ value: {
51
+ role: "renderer",
52
+ path: first,
53
+ resolution_context: "module-specifier",
54
+ mechanism: `call:${name}`,
55
+ module_key: null,
56
+ location: range(node),
57
+ },
58
+ });
59
+ };
60
+ const requireCallSpecifier = (node, name, moduleRequireName) => {
61
+ if (name === "require" || name.endsWith(".require"))
62
+ return { specifier: argumentValue(node.arguments[0]) };
63
+ if (name === "__webpack_require__" || name === moduleRequireName)
64
+ return { specifier: argumentValue(node.arguments[0]) };
65
+ if (name === "__webpack_require__.bind" ||
66
+ (moduleRequireName !== null && name === `${moduleRequireName}.bind`))
67
+ return { specifier: argumentValue(node.arguments[1]) };
68
+ return null;
69
+ };
70
+ const chunkLoadSpecifier = (node, name, moduleRequireName) => {
71
+ if (name !== "__webpack_require__.e" &&
72
+ (moduleRequireName === null || name !== `${moduleRequireName}.e`))
73
+ return null;
74
+ return { specifier: prefixedArgument("chunk:", node.arguments[0]) };
75
+ };
76
+ const inspectEndpointCall = (node, name, first, context) => {
77
+ const route = STATIC_ROUTE_CALL_NAMES.some((candidate) => name === candidate || name.endsWith(`.${candidate}`));
78
+ if (route && first !== undefined)
79
+ addEndpoint(context, {
80
+ node,
81
+ kind: "route",
82
+ value: first,
83
+ mechanism: `call:${name}`,
84
+ });
85
+ const endpoint = endpointArgumentHelper(name, node.arguments);
86
+ if (endpoint !== undefined)
87
+ addEndpoint(context, {
88
+ node,
89
+ kind: "network",
90
+ value: endpoint,
91
+ mechanism: `call:${name}`,
92
+ });
93
+ };
94
+ export const inspectRouteProperty = (node, context) => {
95
+ const key = propertyName(node.key);
96
+ if ((key === "path" || key === "route") && t.isStringLiteral(node.value))
97
+ addEndpoint(context, {
98
+ node,
99
+ kind: "route",
100
+ value: node.value.value,
101
+ mechanism: `property:${key}`,
102
+ });
103
+ };
104
+ export const inspectRoleProperty = (node, context) => {
105
+ if (propertyName(node.key) !== "preload")
106
+ return;
107
+ const path = staticPath(node.value);
108
+ if (path === undefined)
109
+ return;
110
+ addLocatedFinding(context, {
111
+ collection: context.accumulator.roles,
112
+ key: `role\0preload\0${path}`,
113
+ node,
114
+ value: {
115
+ role: "preload",
116
+ path,
117
+ resolution_context: staticPathResolutionContext(node.value),
118
+ mechanism: "property:preload",
119
+ module_key: null,
120
+ location: range(node),
121
+ },
122
+ });
123
+ };
124
+ const inspectStorageCall = (node, name, first, context) => {
125
+ const storage = storageKind(name);
126
+ if (storage === undefined)
127
+ return;
128
+ addLocatedFinding(context, {
129
+ collection: context.accumulator.storage,
130
+ key: `storage\0${storage}\0${first ?? ""}`,
131
+ node,
132
+ value: {
133
+ kind: storage,
134
+ name: first ?? null,
135
+ mechanism: `call:${name}`,
136
+ module_key: null,
137
+ location: range(node),
138
+ },
139
+ });
140
+ };
141
+ export const addReference = (context, input) => {
142
+ const boundedSpecifier = input.specifier?.slice(0, 4_096) ?? null;
143
+ const expression = boundedSpecifier === null
144
+ ? sourceSlice(context.source, input.node).slice(0, 4_096)
145
+ : null;
146
+ addLocatedFinding(context, {
147
+ collection: context.accumulator.references,
148
+ key: `reference\0${input.kind}\0${boundedSpecifier ?? expression}`,
149
+ node: input.node,
150
+ value: {
151
+ kind: input.kind,
152
+ specifier: boundedSpecifier,
153
+ expression,
154
+ module_key: null,
155
+ location: range(input.node),
156
+ },
157
+ });
158
+ };
159
+ const addEndpoint = (context, input) => addLocatedFinding(context, {
160
+ collection: context.accumulator.endpoints,
161
+ key: `endpoint\0${input.kind}\0${input.value}`,
162
+ node: input.node,
163
+ value: {
164
+ kind: input.kind,
165
+ value: sanitizeCandidate(input.value),
166
+ mechanism: input.mechanism,
167
+ module_key: null,
168
+ location: range(input.node),
169
+ },
170
+ });
171
+ export const addSourceMapDirectives = (source, accumulator, maximum) => {
172
+ for (const match of source.matchAll(/\/\/[#@]\s*sourceMappingURL\s*=\s*([^\s]+)/gu)) {
173
+ const declared = match[1]?.slice(0, 4_096);
174
+ if (declared === undefined)
175
+ continue;
176
+ const start = match.index;
177
+ const location = rangeForOffsets(source, start, start + match[0].length);
178
+ addBoundedFinding(accumulator, `source-map\0${declared}`, maximum, () => accumulator.sourceMaps.push({ declared_url: declared, location }));
179
+ }
180
+ };
@@ -101,6 +101,10 @@ export const staticArrayValues = (array, maximum) => {
101
101
  };
102
102
  /** Resolve a bounded path composed only from inert literal syntax. */
103
103
  export const staticPath = (node) => staticPathAt(node, 0);
104
+ /** Classify whether inert path syntax is a module specifier or file expression. */
105
+ export const staticPathResolutionContext = (node) => isFilesystemPathExpression(node, 0)
106
+ ? "filesystem-expression"
107
+ : "module-specifier";
104
108
  const staticPathAt = (node, depth) => {
105
109
  if (depth >= 128)
106
110
  return undefined;
@@ -124,12 +128,23 @@ const staticPathAt = (node, depth) => {
124
128
  const staticCallPath = (node, depth) => {
125
129
  const name = calleeName(node.callee);
126
130
  if (name === "URL" || name.endsWith(".URL"))
127
- return stringValue(node.arguments[0]);
131
+ return isFileIdentity(argumentNode(node.arguments[1]))
132
+ ? stringValue(node.arguments[0])
133
+ : undefined;
134
+ if (name === "fileURLToPath" || name.endsWith(".fileURLToPath")) {
135
+ const argument = argumentNode(node.arguments[0]);
136
+ return argument === undefined
137
+ ? undefined
138
+ : staticPathAt(argument, depth + 1);
139
+ }
140
+ if ((name === "dirname" || name.endsWith(".dirname")) &&
141
+ isFileIdentity(argumentNode(node.arguments[0])))
142
+ return "";
128
143
  if (!name.endsWith(".join") && !name.endsWith(".resolve") && name !== "join")
129
144
  return undefined;
130
145
  const parts = [];
131
146
  for (const argument of node.arguments) {
132
- if (t.isIdentifier(argument, { name: "__dirname" }))
147
+ if (isDirectoryIdentity(argumentNode(argument)))
133
148
  continue;
134
149
  const value = t.isNode(argument)
135
150
  ? staticPathAt(argument, depth + 1)
@@ -140,6 +155,60 @@ const staticCallPath = (node, depth) => {
140
155
  }
141
156
  return parts.length === 0 ? undefined : posix.join(...parts).slice(0, 4_096);
142
157
  };
158
+ const isFilesystemPathExpression = (node, depth) => {
159
+ if (depth >= 128)
160
+ return false;
161
+ if (t.isStringLiteral(node))
162
+ return node.value.startsWith("/");
163
+ if (isFileIdentity(node) || isDirectoryIdentity(node))
164
+ return true;
165
+ if (t.isBinaryExpression(node, { operator: "+" }))
166
+ return (isFilesystemPathExpression(node.left, depth + 1) ||
167
+ isFilesystemPathExpression(node.right, depth + 1));
168
+ if (t.isCallExpression(node) || t.isNewExpression(node)) {
169
+ const name = calleeName(node.callee);
170
+ if (name === "URL" || name.endsWith(".URL"))
171
+ return isFileIdentity(argumentNode(node.arguments[1]));
172
+ if (name === "fileURLToPath" || name.endsWith(".fileURLToPath"))
173
+ return node.arguments.some((argument) => {
174
+ const value = argumentNode(argument);
175
+ return (value !== undefined && isFilesystemPathExpression(value, depth + 1));
176
+ });
177
+ return node.arguments.some((argument) => {
178
+ const value = argumentNode(argument);
179
+ return (value !== undefined && isFilesystemPathExpression(value, depth + 1));
180
+ });
181
+ }
182
+ return false;
183
+ };
184
+ const isDirectoryIdentity = (node) => {
185
+ if (t.isIdentifier(node, { name: "__dirname" }))
186
+ return true;
187
+ if (!t.isCallExpression(node) && !t.isNewExpression(node))
188
+ return false;
189
+ const name = calleeName(node.callee);
190
+ if (name === "URL" || name.endsWith(".URL"))
191
+ return isFileIdentity(argumentNode(node.arguments[1]));
192
+ return ((name === "dirname" || name.endsWith(".dirname")) &&
193
+ isFileIdentity(argumentNode(node.arguments[0])));
194
+ };
195
+ const isFileIdentity = (node) => {
196
+ if (t.isIdentifier(node, { name: "__filename" }))
197
+ return true;
198
+ if (node === undefined)
199
+ return false;
200
+ if (t.isMemberExpression(node) &&
201
+ t.isMetaProperty(node.object) &&
202
+ node.object.meta.name === "import" &&
203
+ node.object.property.name === "meta" &&
204
+ propertyName(node.property) === "url")
205
+ return true;
206
+ if (!t.isCallExpression(node))
207
+ return false;
208
+ const name = calleeName(node.callee);
209
+ return ((name === "fileURLToPath" || name.endsWith(".fileURLToPath")) &&
210
+ isFileIdentity(argumentNode(node.arguments[0])));
211
+ };
143
212
  /** Select the literal URL argument for recognized network callees. */
144
213
  export const endpointArgument = (name, args) => {
145
214
  if (name === "fetch" || name.endsWith(".fetch") || name === "WebSocket")
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Assess source-page and downstream-projection completeness without treating an
3
+ * unreturned row as absent. `includedCount` is the number retained downstream.
4
+ */
5
+ export const assessKnownPageCoverage = (page, includedCount = page.items.length) => {
6
+ const observedCount = Math.min(page.total, page.returned, page.items.length);
7
+ const retainedCount = Math.min(observedCount, Math.max(0, Math.floor(includedCount)));
8
+ const sourceOmittedCount = Math.max(0, page.total - observedCount);
9
+ const sourceComplete = page.complete &&
10
+ page.offset === 0 &&
11
+ page.returned === page.total &&
12
+ sourceOmittedCount === 0;
13
+ const omittedCount = Math.max(0, page.total - retainedCount);
14
+ return {
15
+ complete: sourceComplete && omittedCount === 0,
16
+ sourceComplete,
17
+ includedCount: retainedCount,
18
+ omittedCount,
19
+ sourceOmittedCount,
20
+ };
21
+ };