rea-agents 2.0.0 → 2.1.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 (246) hide show
  1. package/README.md +78 -32
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +24 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +1 -23
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +156 -238
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +23 -7
  26. package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
  27. package/dist/application/EnhancedToolPagination.js +22 -0
  28. package/dist/application/EnhancedToolTypes.js +4 -0
  29. package/dist/application/EnhancedTools.js +20 -37
  30. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  31. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  32. package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
  33. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  34. package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
  35. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  36. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  37. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  38. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  39. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  40. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  41. package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
  42. package/dist/application/JavaScriptJsonModules.js +39 -0
  43. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  44. package/dist/application/JavaScriptReplayPermission.js +16 -0
  45. package/dist/application/JavaScriptReplayService.js +182 -156
  46. package/dist/application/LinuxHopper.js +10 -0
  47. package/dist/application/MacHopper.js +22 -11
  48. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  49. package/dist/application/PermissionAuthority.js +106 -63
  50. package/dist/application/ProcessCaptureCapability.js +1 -1
  51. package/dist/application/ProcessCapturePermission.js +13 -0
  52. package/dist/application/ProcessCli.js +2 -12
  53. package/dist/application/ProcessHarness.js +1 -1
  54. package/dist/application/ProjectPermissionStore.js +48 -9
  55. package/dist/application/RealHopperAssertions.js +76 -0
  56. package/dist/application/ReconstructionCoverageService.js +69 -0
  57. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  58. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  59. package/dist/application/Setup.js +147 -259
  60. package/dist/application/SetupClientConfiguration.js +220 -0
  61. package/dist/application/SetupClients.js +24 -2
  62. package/dist/application/SetupPlan.js +123 -12
  63. package/dist/application/SetupSkill.js +26 -12
  64. package/dist/application/SupportedClients.js +1 -0
  65. package/dist/application/Uninstall.js +6 -3
  66. package/dist/application/WindowsCapabilities.js +86 -0
  67. package/dist/artifacts/AsarArtifactReader.js +11 -0
  68. package/dist/browser/BrowserProcessStartup.js +88 -0
  69. package/dist/browser/CdpCaptureDocuments.js +12 -8
  70. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  71. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  72. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  73. package/dist/browser/CdpCaptureEventState.js +1 -0
  74. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  75. package/dist/browser/CdpCaptureEvents.js +29 -496
  76. package/dist/browser/CdpObservationSession.js +51 -8
  77. package/dist/browser/CdpPageCapture.js +12 -133
  78. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  79. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  80. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  81. package/dist/browser/PngVisualDiff.js +9 -2
  82. package/dist/catalogIdentity.js +4 -0
  83. package/dist/cli/artifactCommands.js +82 -0
  84. package/dist/cli/coreAnalysisCommands.js +232 -0
  85. package/dist/cli/managedCommands.js +397 -0
  86. package/dist/cli/managedProjectGraphCommand.js +24 -0
  87. package/dist/cli/options.js +9 -0
  88. package/dist/cli/setupCommands.js +108 -0
  89. package/dist/cli/types.js +1 -0
  90. package/dist/cli/utilityCommands.js +122 -0
  91. package/dist/cli.js +10 -768
  92. package/dist/cliApplicationCommands.js +118 -4
  93. package/dist/cliBrowserAdvancedCommands.js +73 -16
  94. package/dist/cliBrowserCommands.js +39 -115
  95. package/dist/cliCommandNames.js +4 -0
  96. package/dist/cliElectronCommands.js +33 -62
  97. package/dist/cliEvidenceCommands.js +13 -2
  98. package/dist/cliInvestigationCommands.js +53 -10
  99. package/dist/cliObservationOptions.js +137 -0
  100. package/dist/cliPolicyCommands.js +80 -46
  101. package/dist/cliSetup.js +289 -0
  102. package/dist/config/environment.js +107 -0
  103. package/dist/config/parseConfig.js +228 -0
  104. package/dist/config/parsers.js +68 -0
  105. package/dist/config/permissions.js +30 -0
  106. package/dist/config/types.js +1 -0
  107. package/dist/config.js +1 -375
  108. package/dist/contracts/applicationToolContracts.js +134 -0
  109. package/dist/contracts/managedToolContracts.js +1 -1
  110. package/dist/contracts/managedWorkflowToolContracts.js +3 -3
  111. package/dist/contracts/providerSelection.js +2 -0
  112. package/dist/contracts/toolContracts.js +2 -2
  113. package/dist/contracts/toolEffects.js +14 -0
  114. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  115. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  116. package/dist/contracts/toolOutputSchemas.js +2 -550
  117. package/dist/domain/analysisErrorPresentation.js +234 -0
  118. package/dist/domain/analysisErrorProjection.js +284 -0
  119. package/dist/domain/artifactComparison.js +34 -15
  120. package/dist/domain/binaryTarget.js +87 -37
  121. package/dist/domain/browserObservation.js +1 -285
  122. package/dist/domain/browserObservationSchemas.js +286 -0
  123. package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
  124. package/dist/domain/errors.js +4 -486
  125. package/dist/domain/functionComparison.js +4 -165
  126. package/dist/domain/functionComparisonDimensions.js +164 -0
  127. package/dist/domain/javascriptApplicationVersionItems.js +18 -6
  128. package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
  129. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  130. package/dist/domain/javascriptFeatureTraversal.js +19 -7
  131. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
  132. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  133. package/dist/domain/javascriptSemanticIr.js +30 -0
  134. package/dist/domain/javascriptSemanticProjection.js +366 -0
  135. package/dist/domain/javascriptSemanticState.js +40 -0
  136. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  137. package/dist/domain/javascriptSemanticValues.js +352 -0
  138. package/dist/domain/javascriptStaticAnalysis.js +5 -221
  139. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  140. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  141. package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
  142. package/dist/domain/knownPageCoverage.js +21 -0
  143. package/dist/domain/managedApplicationGraph.js +14 -364
  144. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  145. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  146. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  147. package/dist/domain/managedArtifact.js +16 -8
  148. package/dist/domain/managedMemberComparison.js +37 -391
  149. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  150. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  151. package/dist/domain/managedNativeVerification.js +27 -389
  152. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  153. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  154. package/dist/domain/managedReconstruction.js +82 -69
  155. package/dist/domain/managedRuntimeCorrelation.js +12 -3
  156. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  157. package/dist/domain/permissionPolicy.js +2 -0
  158. package/dist/domain/reconstructionCoverage.js +387 -0
  159. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  160. package/dist/domain/reconstructionVerificationSchemas.js +8 -0
  161. package/dist/domain/runtimeCharacterization.js +85 -0
  162. package/dist/domain/webBundleAnalyzer.js +3 -409
  163. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  164. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  165. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  166. package/dist/dotnet/ManagedArtifactInspector.js +50 -29
  167. package/dist/dotnet/ManagedMemberInspector.js +51 -785
  168. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  169. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  170. package/dist/dotnet/ManagedMemberRows.js +120 -0
  171. package/dist/dotnet/ManagedMetadataInventory.js +42 -306
  172. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  173. package/dist/dotnet/ManagedMetadataLayout.js +48 -111
  174. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  175. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  176. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  177. package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
  178. package/dist/dotnet/ManagedPeReader.js +59 -28
  179. package/dist/generatedPackageMetadata.js +2 -2
  180. package/dist/ghidra/GhidraClient.js +76 -91
  181. package/dist/ghidra/GhidraClientStartup.js +29 -0
  182. package/dist/ghidra/GhidraClientWire.js +34 -0
  183. package/dist/ghidra/GhidraDefaults.js +1 -1
  184. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  185. package/dist/ghidra/GhidraInstallation.js +20 -15
  186. package/dist/ghidra/GhidraLauncher.js +93 -29
  187. package/dist/ghidra/GhidraProvider.js +61 -161
  188. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  189. package/dist/ghidra/GhidraSessionValues.js +2 -0
  190. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  191. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  192. package/dist/ghidra/GhidraTransport.js +71 -0
  193. package/dist/identity.js +3 -2
  194. package/dist/main/messages.js +5 -0
  195. package/dist/main/reload.js +49 -0
  196. package/dist/main/shutdown.js +25 -0
  197. package/dist/main/startup.js +14 -0
  198. package/dist/main/state.js +26 -0
  199. package/dist/main/transport.js +61 -0
  200. package/dist/main/types.js +1 -0
  201. package/dist/main.js +35 -146
  202. package/dist/process/PrivateRuntimeRoot.js +3 -2
  203. package/dist/process/ProcessOwnership.js +35 -0
  204. package/dist/process/ProviderProcess.js +2 -0
  205. package/dist/replay/JavaScriptReplayWorker.js +64 -50
  206. package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
  207. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  208. package/dist/replay/ReplayOutcome.js +95 -0
  209. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  210. package/dist/server/ProcessCaptureElicitation.js +157 -0
  211. package/dist/server/createServer.js +119 -54
  212. package/dist/server/registerApplicationTools/characterization.js +57 -0
  213. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  214. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  215. package/dist/server/registerApplicationTools/coverage.js +84 -0
  216. package/dist/server/registerApplicationTools/helpers.js +42 -0
  217. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  218. package/dist/server/registerApplicationTools/types.js +1 -0
  219. package/dist/server/registerApplicationTools.js +10 -112
  220. package/dist/server/registerBrowserTools.js +59 -83
  221. package/dist/server/registerElectronTools.js +31 -46
  222. package/dist/server/registerEnhancedTools.js +34 -42
  223. package/dist/server/registerEvidenceResources.js +54 -0
  224. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  225. package/dist/server/registerInvestigationTools/types.js +1 -0
  226. package/dist/server/registerInvestigationTools.js +83 -116
  227. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  228. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  229. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  230. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  231. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  232. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  233. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  234. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  235. package/dist/server/registerManagedWorkflowTools.js +10 -274
  236. package/dist/server/registerOfficialTools.js +73 -59
  237. package/dist/server/registerSessionRecordTools.js +137 -0
  238. package/dist/server/registerSessionStatusTool.js +2 -1
  239. package/dist/server/registerSessionTools.js +60 -164
  240. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  241. package/dist/server/toolRegistrationOptions.js +101 -3
  242. package/dist/server/toolResult.js +5 -0
  243. package/package.json +10 -11
  244. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +20 -7
  245. package/scripts/prepare-node-pty.mjs +0 -35
  246. package/scripts/rebuild-native.mjs +0 -22
@@ -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
+ };