rea-agents 6.0.0 → 6.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 (611) hide show
  1. package/README.md +26 -18
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +205 -51
  4. package/bridge/hopper_bridge.py +314 -127
  5. package/bridge/mitmproxy/capture.py +0 -2
  6. package/bridge/native/rea_lldb_tracer.py +630 -94
  7. package/bridge/process/ProcessRunTokenReader.swift +39 -5
  8. package/bridge/pwntools/recorded_crash_impl.py +4 -0
  9. package/dist/android/JadxConfiguration.js +274 -31
  10. package/dist/android/JadxMcpTransport.js +18 -2
  11. package/dist/android/JadxProtocol.js +6 -0
  12. package/dist/android/JadxProvider.js +76 -37
  13. package/dist/android/JadxSession.js +23 -4
  14. package/dist/application/AnalysisContextQueries.js +8 -35
  15. package/dist/application/AnalysisDocument.js +32 -0
  16. package/dist/application/AppBundleExecutable.js +67 -21
  17. package/dist/application/BinaryTargetResolver.js +5 -3
  18. package/dist/application/BrowserEvidence.js +3 -8
  19. package/dist/application/BrowserScenarioEvidence.js +2 -18
  20. package/dist/application/CallPathTracing.js +19 -3
  21. package/dist/application/CapabilityInventory.js +48 -11
  22. package/dist/application/ClientConfigurationDocument.js +917 -8
  23. package/dist/application/ClientRegistrationIdentity.js +26 -5
  24. package/dist/application/ClientRegistrationStatus.js +29 -14
  25. package/dist/application/DirectAnalysis.js +56 -51
  26. package/dist/application/DirectAnalysisCleanup.js +72 -0
  27. package/dist/application/DirectAnalysisStatus.js +4 -5
  28. package/dist/application/Doctor.js +19 -21
  29. package/dist/application/DoctorDiagnostics.js +1 -2
  30. package/dist/application/DoctorScope.js +25 -13
  31. package/dist/application/EnhancedLiteralTracing.js +22 -25
  32. package/dist/application/EnhancedTools.js +64 -17
  33. package/dist/application/EvidenceBundleFiles.js +30 -13
  34. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  35. package/dist/application/InventoryProjectionEvidence.js +4 -3
  36. package/dist/application/InvestigationProviders.js +11 -2
  37. package/dist/application/JsonFiles.js +83 -28
  38. package/dist/application/LinuxHopper.js +9 -6
  39. package/dist/application/MacHopper.js +15 -18
  40. package/dist/application/ProcedureAddressResolution.js +11 -0
  41. package/dist/application/RealHopperAssertions.js +0 -11
  42. package/dist/application/ReconstructionCoverageService.js +7 -4
  43. package/dist/application/ReconstructionObligationCandidates.js +1 -1
  44. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  45. package/dist/application/ReferenceSourceImportEntries.js +1 -1
  46. package/dist/application/Setup.js +21 -17
  47. package/dist/application/SetupClientConfiguration.js +10 -15
  48. package/dist/application/SetupHost.js +21 -29
  49. package/dist/application/SetupPlan.js +11 -9
  50. package/dist/application/SupportedClients.js +34 -1
  51. package/dist/application/Uninstall.js +82 -29
  52. package/dist/application/Update.js +18 -3
  53. package/dist/application/UpdateMaintenance.js +7 -5
  54. package/dist/application/UpdateRuntime.js +57 -36
  55. package/dist/application/WebModuleTraceService.js +4 -2
  56. package/dist/application/WebNetworkCaptureService.js +4 -2
  57. package/dist/application/WebRuntimeService.js +5 -3
  58. package/dist/application/WebScriptExportService.js +32 -6
  59. package/dist/application/WebSourceLocationService.js +4 -2
  60. package/dist/application/WorkflowEvidence.js +105 -0
  61. package/dist/application/XrefsAddressResolution.js +45 -0
  62. package/dist/application/analysisView/AnalysisViewService.js +76 -0
  63. package/dist/application/binary/AnalysisClientCleanup.js +30 -5
  64. package/dist/application/binary/AnalysisProviderEvaluation.js +22 -7
  65. package/dist/application/binary/AnalysisProviderRegistry.js +4 -6
  66. package/dist/application/binary/AnalysisSnapshotCache.js +13 -14
  67. package/dist/application/binary/BinarySession.js +161 -93
  68. package/dist/application/binary/BinarySessionComposition.js +1 -3
  69. package/dist/application/binary/BinarySessionExecution.js +3 -5
  70. package/dist/application/binary/BinarySessionOpen.js +4 -4
  71. package/dist/application/binary/BinarySessionRecords.js +26 -4
  72. package/dist/application/binary/BinarySessionStatus.js +18 -7
  73. package/dist/application/binary/CompositeProvider.js +16 -17
  74. package/dist/application/binary/LazyAnalysisProvider.js +8 -5
  75. package/dist/application/binary/SessionProviderRouter.js +27 -135
  76. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
  77. package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
  78. package/dist/application/evm/EvmInterfaceService.js +4 -2
  79. package/dist/application/homebrew.js +48 -0
  80. package/dist/application/investigation/EvidenceLedger.js +21 -7
  81. package/dist/application/investigation/InvestigationRecords.js +8 -0
  82. package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
  83. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  84. package/dist/application/javascript/JavaScriptApplicationEvidence.js +21 -4
  85. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  86. package/dist/application/javascript/JavaScriptApplicationService.js +27 -15
  87. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  88. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +10 -7
  89. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +44 -10
  90. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
  91. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
  92. package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
  93. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
  94. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
  95. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +49 -19
  96. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +56 -8
  97. package/dist/application/javascript/JavaScriptModuleRelationships.js +38 -9
  98. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  99. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +6 -4
  100. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  101. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
  102. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
  103. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
  104. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
  105. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
  106. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
  107. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
  108. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +64 -19
  109. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  110. package/dist/application/managed/ManagedMemberComparisonService.js +9 -5
  111. package/dist/application/managed/ManagedNativeVerificationService.js +6 -4
  112. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  113. package/dist/application/process/ProcessCli.js +25 -17
  114. package/dist/application/process/ProcessEvidence.js +4 -4
  115. package/dist/application/workflowInputError.js +18 -0
  116. package/dist/artifacts/ArtifactProvider.js +48 -13
  117. package/dist/artifacts/ArtifactReader.js +31 -0
  118. package/dist/artifacts/DirectoryArtifactReader.js +2 -1
  119. package/dist/artifacts/MachOSliceArtifactReader.js +106 -15
  120. package/dist/artifacts/NativeDmgArtifactReader.js +73 -21
  121. package/dist/artifacts/SafeOutputTree.js +16 -2
  122. package/dist/artifacts/ZipArtifactReader.js +11 -4
  123. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +26 -5
  124. package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
  125. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  126. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  127. package/dist/artifacts/apple/KeyedArchiveReader.js +55 -23
  128. package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
  129. package/dist/artifacts/apple/NibArchive.js +81 -14
  130. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  131. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  132. package/dist/artifacts/extraction/ArtifactExtraction.js +78 -21
  133. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +79 -68
  134. package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
  135. package/dist/artifacts/inventory/reader.js +3 -3
  136. package/dist/artifacts/inventory/scanCanonical.js +59 -38
  137. package/dist/artifacts/inventory/scanReader.js +5 -9
  138. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  139. package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
  140. package/dist/browser/CdpBrowserProvider.js +2 -3
  141. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  142. package/dist/browser/CdpCaptureEventHandlers.js +78 -15
  143. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  144. package/dist/browser/CdpCaptureEvents.js +25 -1
  145. package/dist/browser/CdpCaptureValues.js +20 -0
  146. package/dist/browser/CdpConnection.js +30 -11
  147. package/dist/browser/CdpElectronProvider.js +0 -2
  148. package/dist/browser/CdpElectronScriptEvents.js +2 -8
  149. package/dist/browser/CdpElectronScripts.js +2 -3
  150. package/dist/browser/CdpOptionalCommand.js +2 -3
  151. package/dist/browser/CdpPageCapture.js +23 -1
  152. package/dist/browser/CdpPageCaptureScripts.js +2 -3
  153. package/dist/browser/CdpSafeMetadata.js +10 -10
  154. package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
  155. package/dist/browser/PlaywrightElectronActiveActions.js +34 -79
  156. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  157. package/dist/browser/PlaywrightElectronActiveProvider.js +133 -130
  158. package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
  159. package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
  160. package/dist/browser/PlaywrightScenarioEvents.js +1 -1
  161. package/dist/browser/PlaywrightScenarioSession.js +39 -22
  162. package/dist/browser/WebSourceMapFetcher.js +426 -72
  163. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  164. package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
  165. package/dist/browser/history/CaptureFailures.js +41 -1
  166. package/dist/browser/history/CaptureRelease.js +5 -0
  167. package/dist/browser/history/HarCaptureAdapter.js +3 -3
  168. package/dist/browser/history/HarJson.js +3 -2
  169. package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
  170. package/dist/browser/history/MitmproxyCaptureAdapter.js +4 -2
  171. package/dist/catalogIdentity.js +0 -1
  172. package/dist/cli/analysisSelector.js +23 -0
  173. package/dist/cli/analysisViewCommands.js +36 -0
  174. package/dist/cli/applicationCommands.js +2 -3
  175. package/dist/cli/artifactCommands.js +11 -12
  176. package/dist/cli/coreAnalysisCommands.js +3 -3
  177. package/dist/cli/coreBinaryCommands.js +100 -37
  178. package/dist/cli/coreNativeCommands.js +9 -10
  179. package/dist/cli/electronCommands.js +10 -9
  180. package/dist/cli/interactiveSetup.js +6 -6
  181. package/dist/cli/javascriptApplicationAnalysis.js +7 -3
  182. package/dist/cli/jsonOutput.js +4 -99
  183. package/dist/cli/managedCommands.js +7 -8
  184. package/dist/cli/nativeCallCommands.js +3 -5
  185. package/dist/cli/omittableDefaults.js +50 -0
  186. package/dist/cli/processCommands.js +3 -2
  187. package/dist/cli/setupCommands.js +16 -15
  188. package/dist/cli/utilityCommands.js +9 -9
  189. package/dist/cli/webRuntimeCommands.js +8 -8
  190. package/dist/cli.js +18 -9
  191. package/dist/cliBrowserScenarioCommands.js +2 -2
  192. package/dist/cliCommandNames.js +1 -1
  193. package/dist/cliJsonInput.js +24 -5
  194. package/dist/cliOutput.js +0 -38
  195. package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
  196. package/dist/composition/binary.js +9 -9
  197. package/dist/composition/browserScenario.js +2 -1
  198. package/dist/composition/directAnalysis.js +20 -13
  199. package/dist/composition/electronScenario.js +1 -1
  200. package/dist/composition/optionalObservationProviders.js +12 -7
  201. package/dist/config/environment.js +10 -0
  202. package/dist/config/ghidraStartupTimeout.js +12 -0
  203. package/dist/config/homeDirectory.js +12 -0
  204. package/dist/config/mcpResponseBudget.js +30 -0
  205. package/dist/config/parseConfig.js +8 -3
  206. package/dist/config/parsers.js +19 -22
  207. package/dist/contracts/analysisViewToolContracts.js +56 -0
  208. package/dist/contracts/applicationToolContracts.js +5 -4
  209. package/dist/contracts/artifactComparisonExample.js +2 -2
  210. package/dist/contracts/artifactToolContracts.js +1 -1
  211. package/dist/contracts/browserScenarioToolContracts.js +1 -1
  212. package/dist/contracts/browserToolContracts.js +19 -15
  213. package/dist/contracts/enhancedInputs.js +7 -5
  214. package/dist/contracts/enhancedToolContracts.js +7 -6
  215. package/dist/contracts/evm/evmToolContracts.js +1 -1
  216. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  217. package/dist/contracts/hopperMemoryContracts.js +2 -5
  218. package/dist/contracts/inputSchemaPresentation.js +90 -0
  219. package/dist/contracts/investigationExamples.js +4 -3
  220. package/dist/contracts/javascript/electronToolContracts.js +2 -2
  221. package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
  222. package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
  223. package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
  224. package/dist/contracts/managed/managedToolContracts.js +7 -14
  225. package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
  226. package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
  227. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
  228. package/dist/contracts/native/nativeToolContracts.js +5 -3
  229. package/dist/contracts/officialToolContracts.js +16 -16
  230. package/dist/contracts/promptContracts.js +5 -5
  231. package/dist/contracts/providerSelection.js +1 -1
  232. package/dist/contracts/sessionLifecycleInputs.js +3 -7
  233. package/dist/contracts/sessionStatusContract.js +2 -4
  234. package/dist/contracts/sessionToolContracts.js +18 -8
  235. package/dist/contracts/sessionToolSchemas.js +3 -19
  236. package/dist/contracts/toolContractExamples.js +0 -1
  237. package/dist/contracts/toolContractHelpers.js +4 -1
  238. package/dist/contracts/toolContracts.js +2 -0
  239. package/dist/contracts/toolEffects.js +1 -1
  240. package/dist/contracts/toolOutputSchemaGroups.js +160 -115
  241. package/dist/contracts/toolOutputSchemaPrimitives.js +28 -20
  242. package/dist/contracts/toolSchemaMetadata.js +41 -33
  243. package/dist/contracts/webNetworkCaptureToolContracts.js +2 -2
  244. package/dist/contracts/webRuntimeToolContracts.js +1 -1
  245. package/dist/contracts/webScriptToolContracts.js +1 -1
  246. package/dist/doctorRuntime.js +7 -5
  247. package/dist/domain/analysisErrorBase.js +8 -3
  248. package/dist/domain/analysisErrorCore.js +6 -1
  249. package/dist/domain/analysisErrorPresentation.js +90 -20
  250. package/dist/domain/analysisErrorProjection.js +130 -32
  251. package/dist/domain/analysisSnapshot.js +29 -31
  252. package/dist/domain/analysisView/analysisView.js +243 -0
  253. package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
  254. package/dist/domain/analysisView/binaryLayoutView.js +159 -0
  255. package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
  256. package/dist/domain/android/androidAnalysis.js +2 -4
  257. package/dist/domain/android/androidApplication.js +18 -10
  258. package/dist/domain/apple/appleApplication.js +42 -15
  259. package/dist/domain/apple/dyldEnvironment.js +73 -0
  260. package/dist/domain/apple/dylibResolution.js +130 -12
  261. package/dist/domain/apple/dylibResolutionFindings.js +9 -7
  262. package/dist/domain/apple/interfaceBuilderGraph.js +25 -14
  263. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  264. package/dist/domain/apple/keyedArchive.js +35 -3
  265. package/dist/domain/apple/machoContainer.js +54 -0
  266. package/dist/domain/apple/plistNumbers.js +76 -0
  267. package/dist/domain/artifactComparison.js +15 -6
  268. package/dist/domain/artifactGraph.js +16 -3
  269. package/dist/domain/artifactIdentity.js +29 -0
  270. package/dist/domain/artifactInventoryEvidence.js +28 -40
  271. package/dist/domain/artifactOperationError.js +3 -3
  272. package/dist/domain/artifactPartialObservation.js +1 -0
  273. package/dist/domain/artifactPathSyntax.js +49 -0
  274. package/dist/domain/binaryTarget.js +39 -13
  275. package/dist/domain/bridgeCandidateProjection.js +71 -0
  276. package/dist/domain/browserCaptureComparison.js +13 -49
  277. package/dist/domain/browserCompleteness.js +1 -0
  278. package/dist/domain/browserNetworkEvidence.js +10 -4
  279. package/dist/domain/browserObservation.js +0 -1
  280. package/dist/domain/browserObservationError.js +24 -5
  281. package/dist/domain/browserObservationSchemas.js +14 -3
  282. package/dist/domain/browserScenario.js +0 -1
  283. package/dist/domain/browserScenarioCapture.js +1 -2
  284. package/dist/domain/browserScenarioDiff.js +0 -2
  285. package/dist/domain/browserScenarioDiffEvidence.js +0 -12
  286. package/dist/domain/browserScenarioDiffValues.js +2 -2
  287. package/dist/domain/browserScenarioValues.js +5 -10
  288. package/dist/domain/bundleComparison.js +3 -2
  289. package/dist/domain/callPath.js +8 -9
  290. package/dist/domain/callPathSchemas.js +2 -2
  291. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  292. package/dist/domain/canonicalOrdering.js +9 -5
  293. package/dist/domain/changedBehavior.js +9 -9
  294. package/dist/domain/comparisonSourceEvidence.js +40 -0
  295. package/dist/domain/completionLedgerGeneration.js +2 -1
  296. package/dist/domain/configurationErrors.js +13 -1
  297. package/dist/domain/conformancePackage.js +4 -3
  298. package/dist/domain/evidence.js +65 -36
  299. package/dist/domain/evidenceBundle.js +47 -8
  300. package/dist/domain/evidenceCompletionLedger.js +2 -1
  301. package/dist/domain/evidenceErrors.js +12 -1
  302. package/dist/domain/explicitSensitiveFailure.js +17 -1
  303. package/dist/domain/firmware/firmwareAnalysis.js +6 -7
  304. package/dist/domain/functionComparison.js +4 -5
  305. package/dist/domain/functionComparisonDimensions.js +120 -87
  306. package/dist/domain/functionComparisonNormalization.js +23 -34
  307. package/dist/domain/functionComparisonResults.js +1 -4
  308. package/dist/domain/functionComparisonSchemas.js +2 -8
  309. package/dist/domain/functionDossierEvidence.js +2 -37
  310. package/dist/domain/hopperErrors.js +23 -2
  311. package/dist/domain/hopperValues.js +51 -8
  312. package/dist/domain/immutableJson.js +114 -0
  313. package/dist/domain/inputIssueProjection.js +3 -0
  314. package/dist/domain/javascript/electronActiveObservation.js +47 -64
  315. package/dist/domain/javascript/electronObservation.js +14 -3
  316. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
  317. package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
  318. package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
  319. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  320. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  321. package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
  322. package/dist/domain/javascript/javascriptApplicationGraph.js +39 -3
  323. package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
  324. package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
  325. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
  326. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  327. package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
  328. package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
  329. package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
  330. package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
  331. package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
  332. package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
  333. package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
  334. package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
  335. package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
  336. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  337. package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
  338. package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
  339. package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
  340. package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
  341. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
  342. package/dist/domain/javascript/javascriptSemanticAnalysis.js +106 -5
  343. package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
  344. package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
  345. package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
  346. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  347. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  348. package/dist/domain/javascript/javascriptSemanticDataEffects.js +23 -6
  349. package/dist/domain/javascript/javascriptSemanticGraph.js +98 -43
  350. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  351. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
  352. package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
  353. package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
  354. package/dist/domain/javascript/javascriptSemanticPrimitives.js +18 -21
  355. package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
  356. package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
  357. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  358. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  359. package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
  360. package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
  361. package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
  362. package/dist/domain/javascript/javascriptSemanticValues.js +126 -61
  363. package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
  364. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  365. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  366. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  367. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +16 -5
  368. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  369. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -17
  370. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  371. package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
  372. package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
  373. package/dist/domain/jsonSerialization.js +109 -0
  374. package/dist/domain/jsonValue.js +90 -6
  375. package/dist/domain/localPath.js +6 -0
  376. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  377. package/dist/domain/managed/managedArtifact.js +6 -4
  378. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  379. package/dist/domain/managed/managedMemberComparison.js +2 -9
  380. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  381. package/dist/domain/managed/managedNativeVerification.js +3 -11
  382. package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
  383. package/dist/domain/native/binaryLayout.js +2 -3
  384. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  385. package/dist/domain/native/nativeApiBoundary.js +1 -1
  386. package/dist/domain/native/nativeCallObservation.js +37 -13
  387. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  388. package/dist/domain/native/nativeInstruction.js +7 -0
  389. package/dist/domain/native/recordedCrash.js +2 -3
  390. package/dist/domain/offsetDateTime.js +17 -0
  391. package/dist/domain/process/processCapture.js +21 -16
  392. package/dist/domain/process/processCaptureCoverage.js +67 -0
  393. package/dist/domain/process/processCaptureExample.js +2 -1
  394. package/dist/domain/process/processCaptureParsing.js +1 -34
  395. package/dist/domain/process/processCaptureValidation.js +81 -13
  396. package/dist/domain/process/processComparison.js +79 -26
  397. package/dist/domain/process/processObservation.js +10 -2
  398. package/dist/domain/process/processScenario.js +35 -12
  399. package/dist/domain/process/processTraceComparison.js +0 -2
  400. package/dist/domain/process/processTraceDimensionProjection.js +1 -1
  401. package/dist/domain/process/processTraceEvaluation.js +15 -11
  402. package/dist/domain/process/processTraceSpecification.js +3 -4
  403. package/dist/domain/propertyListKeys.js +1 -1
  404. package/dist/domain/propertyListXmlText.js +19 -0
  405. package/dist/domain/providerAdapterError.js +3 -1
  406. package/dist/domain/providerOperationHealth.js +54 -0
  407. package/dist/domain/reconstructionCoverage.js +5 -2
  408. package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
  409. package/dist/domain/reconstructionReadinessSchemas.js +2 -1
  410. package/dist/domain/reconstructionVerification.js +9 -46
  411. package/dist/domain/reconstructionVerificationSchemas.js +4 -3
  412. package/dist/domain/referenceSourceGraph.js +20 -21
  413. package/dist/domain/staticRuntimeCorrelation.js +8 -45
  414. package/dist/domain/stringPatterns.js +6 -0
  415. package/dist/domain/swiftSymbolClassification.js +61 -0
  416. package/dist/domain/symbolAnalysis.js +66 -18
  417. package/dist/domain/webBundleAnalysis.js +20 -8
  418. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  419. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  420. package/dist/domain/webCaptureDiff.js +0 -1
  421. package/dist/domain/webCaptureDiffSchemas.js +6 -3
  422. package/dist/domain/webEventListeners.js +3 -2
  423. package/dist/domain/webExecution.js +3 -2
  424. package/dist/domain/webRuntime.js +19 -7
  425. package/dist/domain/webScriptExport.js +1 -1
  426. package/dist/domain/webSourceLocation.js +1 -0
  427. package/dist/dotnet/ManagedArtifactInspector.js +2 -19
  428. package/dist/dotnet/ManagedMemberInspector.js +12 -18
  429. package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
  430. package/dist/dotnet/ManagedMemberRows.js +75 -62
  431. package/dist/dotnet/ManagedMetadataInventory.js +16 -22
  432. package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
  433. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
  434. package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
  435. package/dist/dotnet/ManagedReaderFailure.js +16 -0
  436. package/dist/dotnet/ManagedStaticProvider.js +3 -5
  437. package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
  438. package/dist/evaluation/AgentEvaluationReport.js +28 -0
  439. package/dist/evaluation/CodexAgentEval.js +12 -8
  440. package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
  441. package/dist/evm/EvmoleInterfaceProvider.js +2 -1
  442. package/dist/firmware/FirmwareCommand.js +9 -5
  443. package/dist/firmware/FirmwareFiles.js +1 -1
  444. package/dist/firmware/FirmwareProvider.js +4 -4
  445. package/dist/generatedPackageMetadata.js +2 -2
  446. package/dist/ghidra/GhidraAnalysisProfile.js +7 -5
  447. package/dist/ghidra/GhidraClient.js +126 -34
  448. package/dist/ghidra/GhidraClientStartup.js +0 -2
  449. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  450. package/dist/ghidra/GhidraDoctor.js +6 -5
  451. package/dist/ghidra/GhidraFunctionValues.js +13 -12
  452. package/dist/ghidra/GhidraInstallation.js +58 -33
  453. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  454. package/dist/ghidra/GhidraJavaLaunch.js +66 -0
  455. package/dist/ghidra/GhidraLauncher.js +47 -22
  456. package/dist/ghidra/GhidraProvider.js +6 -2
  457. package/dist/ghidra/GhidraProviderCapabilities.js +20 -2
  458. package/dist/ghidra/GhidraProviderClient.js +36 -15
  459. package/dist/ghidra/GhidraSessionError.js +13 -7
  460. package/dist/ghidra/GhidraSessionRoot.js +39 -0
  461. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  462. package/dist/ghidra/GhidraTransport.js +20 -0
  463. package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
  464. package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
  465. package/dist/hopper/BridgeLauncher.js +65 -56
  466. package/dist/hopper/HopperAnalysisProfile.js +65 -12
  467. package/dist/hopper/HopperCleanup.js +63 -22
  468. package/dist/hopper/HopperClient.js +288 -59
  469. package/dist/hopper/HopperFileOffset.js +237 -0
  470. package/dist/hopper/HopperMachOImage.js +197 -0
  471. package/dist/hopper/HopperOperationStage.js +6 -0
  472. package/dist/hopper/HopperProvider.js +71 -19
  473. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  474. package/dist/hopper/HopperRegexSearch.js +134 -0
  475. package/dist/hopper/HopperRegexWorker.js +27 -0
  476. package/dist/hopper/HopperRequestQueue.js +68 -19
  477. package/dist/hopper/HopperTargetLease.js +133 -49
  478. package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
  479. package/dist/ida/IdaConfiguration.js +8 -3
  480. package/dist/ida/IdaInput.js +1 -7
  481. package/dist/ida/IdaMcpConnection.js +8 -4
  482. package/dist/ida/IdaOperationRunner.js +3 -3
  483. package/dist/ida/IdaProvider.js +8 -12
  484. package/dist/ida/IdaSessionClient.js +20 -18
  485. package/dist/ida/IdaWorkspace.js +12 -13
  486. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  487. package/dist/inspector/V8InspectorCaptureProjection.js +9 -4
  488. package/dist/inspector/V8InspectorProvider.js +82 -36
  489. package/dist/javascript/recovery/WakaruCommand.js +7 -2
  490. package/dist/javascript/recovery/WakaruExecution.js +5 -2
  491. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  492. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
  493. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  494. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  495. package/dist/main/shutdown.js +11 -3
  496. package/dist/main/startup.js +9 -2
  497. package/dist/main/transport.js +22 -2
  498. package/dist/main.js +11 -18
  499. package/dist/mcpDoctor.js +62 -2
  500. package/dist/native/AppleDispatchCoverage.js +47 -6
  501. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  502. package/dist/native/AppleDispatchMetadata.js +6 -3
  503. package/dist/native/AppleMachoFixups.js +48 -24
  504. package/dist/native/AppleMachoSelection.js +48 -22
  505. package/dist/native/AppleObjcCategories.js +6 -2
  506. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  507. package/dist/native/AppleObjcProperties.js +2 -1
  508. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  509. package/dist/native/AppleSwiftVtables.js +21 -15
  510. package/dist/native/CommandRunner.js +87 -88
  511. package/dist/native/LldbCallTracer.js +372 -103
  512. package/dist/native/LldbRetainedObservations.js +178 -0
  513. package/dist/native/NativeCallObservation.js +62 -3
  514. package/dist/native/NativeMacOSProvider.js +122 -31
  515. package/dist/native/NativeUiHelperRuntime.js +11 -2
  516. package/dist/native/NativeUiObservation.js +2 -2
  517. package/dist/native/SignatureTargetBinding.js +155 -0
  518. package/dist/native/parsers/lipo.js +71 -1
  519. package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
  520. package/dist/native/pwntools/PwntoolsDecoder.js +2 -1
  521. package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
  522. package/dist/process/DarwinProcessRunTokenReader.js +23 -10
  523. package/dist/process/ExecFileOutput.js +108 -6
  524. package/dist/process/OwnedCommand.js +7 -2
  525. package/dist/process/PrivateRuntimeRoot.js +10 -5
  526. package/dist/process/ProcessOwnership.js +204 -57
  527. package/dist/process/ProcessOwnershipObservation.js +60 -9
  528. package/dist/process/ProviderProcess.js +39 -10
  529. package/dist/process/capture/FilesystemSnapshot.js +50 -13
  530. package/dist/process/capture/ProcessCaptureError.js +15 -2
  531. package/dist/process/capture/ProcessCaptureLifecycle.js +235 -81
  532. package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
  533. package/dist/process/capture/ProcessHarness.js +21 -25
  534. package/dist/process/capture/ProcessNormalization.js +20 -2
  535. package/dist/process/capture/ProcessSampling.js +25 -2
  536. package/dist/process/capture/TerminalRenderer.js +14 -0
  537. package/dist/process/snapshotEnvironment.js +14 -0
  538. package/dist/server/EvidenceMcpServer.js +157 -0
  539. package/dist/server/createServer.js +61 -41
  540. package/dist/server/mcpClientMetadata.js +12 -5
  541. package/dist/server/promptCompletion.js +3 -8
  542. package/dist/server/registerAnalysisViewTool.js +15 -0
  543. package/dist/server/registerAndroidTools.js +2 -5
  544. package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
  545. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  546. package/dist/server/registerApplicationTools/compareVersions.js +4 -5
  547. package/dist/server/registerApplicationTools/coverage.js +1 -2
  548. package/dist/server/registerApplicationTools/helpers.js +1 -4
  549. package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
  550. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
  551. package/dist/server/registerApplicationTools/traceFeature.js +4 -5
  552. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  553. package/dist/server/registerArtifactComparisonTool.js +13 -10
  554. package/dist/server/registerBinaryDiagnosticsTools.js +2 -5
  555. package/dist/server/registerBrowserScenarioTool.js +3 -6
  556. package/dist/server/registerBrowserTools.js +13 -18
  557. package/dist/server/registerBundleComparisonTool.js +5 -7
  558. package/dist/server/registerCloseLifecycleTool.js +9 -20
  559. package/dist/server/registerElectronTools.js +10 -15
  560. package/dist/server/registerEnhancedTools.js +36 -77
  561. package/dist/server/registerEvidenceTools.js +3 -6
  562. package/dist/server/registerEvmTools.js +2 -5
  563. package/dist/server/registerFirmwareTools.js +2 -5
  564. package/dist/server/registerFunctionComparisonTool.js +15 -12
  565. package/dist/server/registerInvestigationTools.js +16 -17
  566. package/dist/server/registerJavaScriptRecoveryTool.js +2 -5
  567. package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -8
  568. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -8
  569. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -7
  570. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -9
  571. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -9
  572. package/dist/server/registerOfficialTools.js +4 -21
  573. package/dist/server/registerProcessComparisonTool.js +74 -48
  574. package/dist/server/registerRecordedCrashTools.js +2 -5
  575. package/dist/server/registerSessionRecordTools.js +19 -24
  576. package/dist/server/registerSessionStatusTool.js +19 -6
  577. package/dist/server/registerSessionTools.js +20 -18
  578. package/dist/server/registerWebModuleTool.js +2 -5
  579. package/dist/server/registerWebNetworkCaptureTool.js +2 -5
  580. package/dist/server/registerWebRuntimeTools.js +4 -9
  581. package/dist/server/registerWebScriptTool.js +2 -5
  582. package/dist/server/registerWebSourceLocationTool.js +2 -5
  583. package/dist/server/runDerivedOperation.js +15 -3
  584. package/dist/server/sessionAvailabilityPolicy.js +0 -1
  585. package/dist/server/toolRegistrationOptions.js +2 -2
  586. package/dist/server/toolResult.js +75 -51
  587. package/dist/server/toolResultEncoding.js +34 -0
  588. package/dist/windows/WindowsNativeLoader.js +1 -0
  589. package/dist/windows/WindowsOwnedProcess.js +60 -15
  590. package/dist/windows/WindowsPrivateRuntime.js +7 -8
  591. package/install.sh +1 -1
  592. package/native/windows/README.md +3 -1
  593. package/native/windows/build/manifest.json +2 -2
  594. package/native/windows/build/rea-windows-x64.node +0 -0
  595. package/package.json +44 -30
  596. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  597. package/scripts/electron-active-hook.cjs +241 -37
  598. package/scripts/rea.mjs +3 -6
  599. package/skills/reverse-engineer-anything/SKILL.md +12 -3
  600. package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
  601. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
  602. package/skills/reverse-engineer-anything/references/javascript-applications.md +20 -3
  603. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
  604. package/dist/config.js +0 -1
  605. package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
  606. package/dist/contracts/process/processCaptureExample.js +0 -2
  607. package/dist/contracts/toolOutputSchemas.js +0 -2
  608. package/dist/ghidra/GhidraDefaults.js +0 -2
  609. package/dist/main/reload.js +0 -12
  610. package/dist/main/state.js +0 -3
  611. package/dist/server/sessionToolPolicies.js +0 -2
@@ -1,3 +1,4 @@
1
+ import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
1
2
  import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
2
3
  import { inspectBundleKeyedArchive } from "./apple/KeyedArchiveReader.js";
3
4
  import { traceDylibResolution } from "./apple/DylibResolutionReader.js";
@@ -7,7 +8,7 @@ import { extractArtifact } from "./extraction/ArtifactExtraction.js";
7
8
  import { analyzeInterfaceBuilderBundle } from "./apple/InterfaceBuilderAnalysis.js";
8
9
  import { analyzeAppleAssetCatalogs } from "./apple/AppleAssetCatalogAnalysis.js";
9
10
  import { ARTIFACT_ANALYSIS_OPERATIONS, artifactInventoryInputSchema, artifactExtractionExecutionSchema, } from "../contracts/artifactToolContracts.js";
10
- import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
11
+ import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisUnsupportedTargetError, } from "../domain/analysisErrorCore.js";
11
12
  import { ArtifactOperationError } from "../domain/artifactOperationError.js";
12
13
  import {} from "../domain/analysisErrorBase.js";
13
14
  import { interfaceBuilderLimitsSchema } from "../domain/apple/interfaceBuilderGraph.js";
@@ -20,8 +21,12 @@ import { resolveArtifactIntegrityPolicy } from "./inventory/policy.js";
20
21
  /** Read-only inventory and exclusively owned extraction provider. */
21
22
  export class ArtifactProvider {
22
23
  #capabilities;
23
- constructor(platform = process.platform) {
24
+ #platform;
25
+ environment;
26
+ constructor(environment, platform = process.platform) {
27
+ this.environment = snapshotEnvironment(environment, platform);
24
28
  this.#capabilities = artifactCapabilities(platform);
29
+ this.#platform = platform;
25
30
  }
26
31
  identity() {
27
32
  return IDENTITY;
@@ -30,13 +35,17 @@ export class ArtifactProvider {
30
35
  return this.#capabilities;
31
36
  }
32
37
  createClient(target) {
33
- return new ArtifactClient(target);
38
+ return new ArtifactClient(target, this.environment, this.#platform);
34
39
  }
35
40
  }
36
41
  class ArtifactClient {
37
42
  target;
38
- constructor(target) {
43
+ environment;
44
+ platform;
45
+ constructor(target, environment, platform) {
39
46
  this.target = target;
47
+ this.environment = environment;
48
+ this.platform = platform;
40
49
  }
41
50
  async execute(operation, parameters, options) {
42
51
  if (operation === "health")
@@ -52,7 +61,7 @@ class ArtifactClient {
52
61
  if (this.target.kind !== "executable" ||
53
62
  this.target.sourcePath === undefined ||
54
63
  !this.target.sourcePath.toLowerCase().endsWith(".app"))
55
- throw new ArtifactReaderFailure("unavailable", "decode_interface_builder requires an active .app bundle target");
64
+ throw this.unsupportedTarget(operation, "decode_interface_builder requires an active .app bundle target");
56
65
  const limits = interfaceBuilderLimitsSchema.parse(parameters);
57
66
  const result = await analyzeInterfaceBuilderBundle({
58
67
  bundlePath: this.target.sourcePath,
@@ -74,19 +83,27 @@ class ArtifactClient {
74
83
  parameters.path !== undefined &&
75
84
  parameters.path !== "." &&
76
85
  parameters.path !== basename(this.target.path))
77
- throw new ArtifactReaderFailure("path", "For an active plist, path must select that archive (omit path or use its basename)");
86
+ throw new AnalysisInputError(operation, undefined, [
87
+ {
88
+ path: ["path"],
89
+ reason: "invalid_value",
90
+ message: "For an active plist, path must select that archive (omit path or use its basename).",
91
+ expected: basename(this.target.path),
92
+ },
93
+ ]);
78
94
  const bundlePath = standalone
79
95
  ? dirname(this.target.path)
80
96
  : this.target.sourcePath;
81
97
  if (bundlePath === undefined ||
82
98
  (!standalone && !bundlePath.toLowerCase().endsWith(".app")))
83
- throw new ArtifactReaderFailure("unavailable", "inspect_keyed_archive requires an active plist or .app bundle");
99
+ throw this.unsupportedTarget(operation, "inspect_keyed_archive requires an active plist or .app bundle");
84
100
  const result = await inspectBundleKeyedArchive({
85
101
  bundlePath,
86
102
  targetSha256: this.target.sha256,
87
103
  parameters: standalone
88
104
  ? { ...parameters, path: basename(this.target.path) }
89
105
  : parameters,
106
+ platform: this.platform,
90
107
  ...(options?.signal === undefined ? {} : { signal: options.signal }),
91
108
  });
92
109
  if (standalone && result.archive_sha256 !== this.target.sha256)
@@ -107,6 +124,7 @@ class ArtifactClient {
107
124
  inputPath: this.target.sourcePath ?? this.target.path,
108
125
  inputFormat: this.target.format,
109
126
  outputRoot: parsed.output_root,
127
+ environment: this.environment,
110
128
  }, options?.signal);
111
129
  return ok(createAnalysisExecution(result, IDENTITY, {
112
130
  rawResult: null,
@@ -131,19 +149,24 @@ class ArtifactClient {
131
149
  }));
132
150
  }
133
151
  catch (cause) {
134
- return err(translateFailure(operation, cause));
152
+ return err(translateArtifactFailure(operation, cause));
135
153
  }
136
154
  }
137
155
  close() {
138
- return Promise.resolve();
156
+ return Promise.resolve(ok(null));
157
+ }
158
+ /** The active target's kind is outside this operation's supported targets. */
159
+ unsupportedTarget(operation, reason) {
160
+ return new AnalysisUnsupportedTargetError(operation, this.target.sourcePath ?? this.target.path, reason);
139
161
  }
140
162
  async inspectAssetCatalog(parameters, options) {
141
163
  const bundlePath = this.target.sourcePath;
142
164
  if (this.target.kind !== "executable" ||
143
165
  bundlePath === undefined ||
144
166
  !bundlePath.toLowerCase().endsWith(".app"))
145
- throw new ArtifactReaderFailure("unavailable", "inspect_asset_catalog requires an active .app bundle target");
167
+ throw this.unsupportedTarget("inspect_asset_catalog", "inspect_asset_catalog requires an active .app bundle target");
146
168
  const result = await analyzeAppleAssetCatalogs({
169
+ environment: this.environment,
147
170
  bundlePath,
148
171
  targetSha256: this.target.sha256,
149
172
  page: parameters,
@@ -159,7 +182,7 @@ class ArtifactClient {
159
182
  }
160
183
  async traceDylibResolution(parameters, options) {
161
184
  if (this.target.kind !== "executable" || this.target.format !== "mach-o")
162
- throw new ArtifactReaderFailure("unavailable", "trace_dylib_resolution requires an active Mach-O or .app bundle target");
185
+ throw this.unsupportedTarget("trace_dylib_resolution", "trace_dylib_resolution requires an active Mach-O or .app bundle target");
163
186
  // Only a target opened from an app bundle directory carries its Info.plist;
164
187
  // a regular file whose name ends in .app is a standalone image.
165
188
  const bundle = this.target.bundleInfoPlist === undefined
@@ -222,6 +245,7 @@ class ArtifactClient {
222
245
  }
223
246
  inventory(parsed, options) {
224
247
  return inventoryArtifact(this.target.sourcePath ?? this.target.path, {
248
+ environment: this.environment,
225
249
  ...(options?.signal === undefined ? {} : { signal: options.signal }),
226
250
  integrity: resolveArtifactIntegrityPolicy({
227
251
  mode: parsed.integrity_policy,
@@ -230,9 +254,20 @@ class ArtifactClient {
230
254
  }
231
255
  }
232
256
  const isArtifactOperation = (operation) => ARTIFACT_ANALYSIS_OPERATIONS.includes(operation);
233
- const translateFailure = (operation, cause) => {
257
+ /** Translate one artifact boundary failure while retaining cleanup evidence. */
258
+ export const translateArtifactFailure = (operation, cause) => {
234
259
  if (cause instanceof ArtifactReaderFailure)
235
- return new ArtifactOperationError(operation, cause.reason, cause.details, cause.message);
260
+ return new ArtifactOperationError(operation, cause.reason, cause.details, cause.message, {
261
+ ...(cause.cleanup === undefined ? {} : { cleanup: cause.cleanup }),
262
+ ...(cause.partialObservation === undefined
263
+ ? {}
264
+ : { partialObservation: cause.partialObservation }),
265
+ });
266
+ // Caller-selection and unsupported-target failures are already typed; keep
267
+ // their correction details instead of reducing them to an I/O failure.
268
+ if (cause instanceof AnalysisInputError ||
269
+ cause instanceof AnalysisUnsupportedTargetError)
270
+ return cause;
236
271
  return new ArtifactOperationError(operation, "io");
237
272
  };
238
273
  const subjectFor = (path, manifest) => ({
@@ -2,10 +2,41 @@
2
2
  export class ArtifactReaderFailure extends Error {
3
3
  reason;
4
4
  details;
5
+ cleanup;
6
+ partialObservation;
5
7
  constructor(reason, message, options, details) {
6
8
  super(message, options);
7
9
  this.reason = reason;
8
10
  this.details = details;
9
11
  this.name = "ArtifactReaderFailure";
12
+ this.cleanup = options?.cleanup;
13
+ this.partialObservation = options?.partialObservation;
14
+ }
15
+ /** Preserve the primary failure while attaching cleanup and any complete observation. */
16
+ static withCleanup(cause, cleanup, partialObservation) {
17
+ const primary = cause instanceof ArtifactReaderFailure
18
+ ? cause
19
+ : new ArtifactReaderFailure("io", errorMessage(cause), { cause });
20
+ const mergedObservation = partialObservation ?? primary.partialObservation;
21
+ return new ArtifactReaderFailure(primary.reason, primary.message, {
22
+ cause: primary,
23
+ cleanup: combineCleanup(primary.cleanup, cleanup),
24
+ ...(mergedObservation === undefined
25
+ ? {}
26
+ : { partialObservation: mergedObservation }),
27
+ }, primary.details);
28
+ }
29
+ /** Give otherwise opaque cleanup failures a concrete owned resource. */
30
+ static cleanupObservation(cause, resource) {
31
+ if (cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined)
32
+ return cause.cleanup;
33
+ return { reason: errorMessage(cause), resources: [resource] };
10
34
  }
11
35
  }
36
+ const combineCleanup = (primary, cleanup) => primary === undefined || primary === cleanup
37
+ ? cleanup
38
+ : {
39
+ reason: `${primary.reason}; ${cleanup.reason}`,
40
+ resources: [...new Set([...primary.resources, ...cleanup.resources])],
41
+ };
42
+ const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
@@ -1,6 +1,7 @@
1
1
  import { constants } from "node:fs";
2
2
  import { lstat, open, opendir, realpath } from "node:fs/promises";
3
3
  import { isAbsolute, join, relative, sep } from "node:path";
4
+ import { compareCodePoints } from "../domain/canonicalOrdering.js";
4
5
  import { ArtifactReaderFailure, } from "./ArtifactReader.js";
5
6
  /** Deterministic, non-symlink-following directory reader. */
6
7
  export class DirectoryArtifactReader {
@@ -38,7 +39,7 @@ export class DirectoryArtifactReader {
38
39
  await handle.close().catch(() => undefined);
39
40
  }
40
41
  await withDirectoryIoContext("inspect directory", directory, () => assertContainedDirectory(root, directory));
41
- children.sort((left, right) => left.localeCompare(right, "en"));
42
+ children.sort(compareCodePoints);
42
43
  const directories = [];
43
44
  for (const name of children) {
44
45
  abortIfNeeded(signal);
@@ -1,8 +1,9 @@
1
1
  import { createReadStream } from "node:fs";
2
- import { stat } from "node:fs/promises";
2
+ import { open as openFile, stat } from "node:fs/promises";
3
3
  import { Readable } from "node:stream";
4
4
  import { XcrunCommandRunner, } from "../native/CommandRunner.js";
5
- import { parseLipoArchitectures } from "../native/parsers/lipo.js";
5
+ import { parseLipoArchitectures, } from "../native/parsers/lipo.js";
6
+ import { readMachoImage } from "./apple/MachoLoadCommandReader.js";
6
7
  import { ArtifactReaderFailure, } from "./ArtifactReader.js";
7
8
  import { streamChunkToBuffer } from "./StreamBytes.js";
8
9
  /** Read-only universal Mach-O slice reader backed by native lipo metadata. */
@@ -11,7 +12,7 @@ export class MachOSliceArtifactReader {
11
12
  runner;
12
13
  format = "file";
13
14
  #command;
14
- constructor(path, runner = new XcrunCommandRunner()) {
15
+ constructor(path, environment, runner = new XcrunCommandRunner(environment)) {
15
16
  this.path = path;
16
17
  this.runner = runner;
17
18
  }
@@ -28,28 +29,75 @@ export class MachOSliceArtifactReader {
28
29
  effects: ["read"],
29
30
  };
30
31
  const fileSize = (await stat(this.path)).size;
31
- for (const architecture of parseLipoArchitectures(captured.value.stdout)) {
32
- if (architecture.file_offset === null || architecture.size === null)
32
+ const architectures = parseLipoArchitectures(captured.value.stdout);
33
+ const structural = await readStructuralSlices(this.path, fileSize);
34
+ if (structural.status === "malformed")
35
+ throw new ArtifactReaderFailure("integrity", `Mach-O structural slice index is malformed: ${structural.reason}`);
36
+ if (structural.status === "unsupported")
37
+ throw new ArtifactReaderFailure("format", `Mach-O structural slice index is unsupported: ${structural.reason}`);
38
+ const slices = structural.status === "parsed" ? structural.slices : null;
39
+ const matchingSlices = new Map();
40
+ if (slices !== null) {
41
+ if (slices.length !== architectures.length)
42
+ throw new ArtifactReaderFailure("integrity", "lipo architecture count disagrees with the Mach-O FAT table");
43
+ const unmatched = [...slices];
44
+ for (const reported of architectures) {
45
+ const match = unmatched.findIndex((observed) => lipoMatchesSlice(reported, observed, slices.length === 1));
46
+ if (match < 0)
47
+ throw new ArtifactReaderFailure("integrity", `lipo slice metadata disagrees with the Mach-O FAT table: ${reported.name} (cputype=${reported.cpu_type ?? "unknown"}, cpusubtype=${reported.cpu_subtype ?? "unknown"}, offset=${reported.file_offset ?? "unknown"}, size=${reported.size ?? "unknown"}, alignment=${reported.alignment ?? "unknown"})`);
48
+ const [observed] = unmatched.splice(match, 1);
49
+ if (observed !== undefined)
50
+ matchingSlices.set(reported, observed);
51
+ }
52
+ }
53
+ for (const architecture of architectures) {
54
+ const structuralSlice = matchingSlices.get(architecture);
55
+ const offset = architecture.file_offset ?? structuralSlice?.slice_offset;
56
+ const sliceSize = architecture.size ?? structuralSlice?.slice_size;
57
+ if (offset === undefined || sliceSize === undefined)
33
58
  throw new ArtifactReaderFailure("integrity", "lipo omitted a universal slice byte range");
34
- if (!Number.isSafeInteger(architecture.file_offset) ||
35
- !Number.isSafeInteger(architecture.size) ||
36
- architecture.file_offset < 0 ||
37
- architecture.size <= 0 ||
38
- !Number.isSafeInteger(architecture.file_offset + architecture.size) ||
39
- architecture.file_offset + architecture.size > fileSize)
59
+ if (!Number.isSafeInteger(offset) ||
60
+ !Number.isSafeInteger(sliceSize) ||
61
+ offset < 0 ||
62
+ sliceSize <= 0 ||
63
+ !Number.isSafeInteger(offset + sliceSize) ||
64
+ offset + sliceSize > fileSize)
40
65
  throw new ArtifactReaderFailure("integrity", `lipo reported an out-of-bounds Mach-O slice: ${architecture.name}`);
41
66
  yield {
42
67
  path: `slices/${architecture.name}`,
43
68
  kind: "slice",
44
- declaredSize: architecture.size,
69
+ declaredSize: sliceSize,
45
70
  compressedSize: null,
46
71
  executable: true,
47
72
  encrypted: false,
48
- byteOffset: architecture.file_offset,
73
+ byteOffset: offset,
49
74
  declaredSha256: null,
50
75
  unpacked: false,
51
- limitations: [],
52
- adapterKey: `${String(architecture.file_offset)}:${String(architecture.size)}`,
76
+ limitations: [
77
+ ...(structural.status === "not-mach-o"
78
+ ? [
79
+ "Structural Mach-O facts were unavailable; slice range is based on lipo output.",
80
+ ]
81
+ : []),
82
+ ...(architecture.file_offset === null || architecture.size === null
83
+ ? [
84
+ "Slice range was derived from structural Mach-O facts because lipo omitted it.",
85
+ ]
86
+ : []),
87
+ ...(architecture.cpu_type !== null &&
88
+ architecture.cpu_type_code === null
89
+ ? [
90
+ `lipo CPU type is retained as unnormalized source text: ${architecture.cpu_type}`,
91
+ ]
92
+ : []),
93
+ ...(architecture.cpu_subtype !== null &&
94
+ architecture.cpu_subtype_code === null
95
+ ? [
96
+ `lipo CPU subtype is retained as unnormalized source text: ${architecture.cpu_subtype}${architecture.capabilities === null ? "" : `; capabilities ${architecture.capabilities}`}`,
97
+ ]
98
+ : []),
99
+ ],
100
+ adapterKey: `${String(offset)}:${String(sliceSize)}`,
53
101
  };
54
102
  }
55
103
  }
@@ -103,6 +151,49 @@ export class MachOSliceArtifactReader {
103
151
  return Promise.resolve();
104
152
  }
105
153
  }
154
+ /** Compare lipo's independent ranges with structurally parsed slice identity. */
155
+ const readStructuralSlices = async (path, size) => {
156
+ const file = await openFile(path, "r");
157
+ try {
158
+ const readAt = async (offset, length) => {
159
+ const bytes = Buffer.alloc(length);
160
+ const { bytesRead } = await file.read(bytes, 0, length, offset);
161
+ return bytes.subarray(0, bytesRead);
162
+ };
163
+ const facts = await readMachoImage(readAt, size);
164
+ return facts;
165
+ }
166
+ finally {
167
+ await file.close();
168
+ }
169
+ };
170
+ const lipoMatchesSlice = (reported, observed, structurallyUnique) => {
171
+ const observedCpuType = observed.fat_cpu_type ?? observed.cpu_type;
172
+ const observedCpuSubtype = observed.fat_cpu_subtype ?? observed.cpu_subtype;
173
+ const hasPhysicalIdentity = reported.file_offset !== null ||
174
+ reported.size !== null ||
175
+ reported.cpu_type_code !== null ||
176
+ reported.cpu_subtype_code !== null;
177
+ return ((hasPhysicalIdentity || structurallyUnique) &&
178
+ lipoNameMatches(reported.name, observed.architecture) &&
179
+ (reported.file_offset === null ||
180
+ reported.file_offset === observed.slice_offset) &&
181
+ (reported.size === null || reported.size === observed.slice_size) &&
182
+ (reported.cpu_type_code === null ||
183
+ reported.cpu_type_code === observedCpuType) &&
184
+ (reported.cpu_subtype_code === null ||
185
+ reported.cpu_subtype_code === observedCpuSubtype) &&
186
+ (reported.alignment === null ||
187
+ observed.fat_alignment_exponent === null ||
188
+ reported.alignment === 2 ** observed.fat_alignment_exponent));
189
+ };
190
+ /**
191
+ * Newer lipo names an arm64e ABI variant `arm64e.<variant>` (for example
192
+ * `arm64e.v1` for pointer-auth ABI version 1). The FAT table names that slice
193
+ * `arm64e`; its physical identity is still compared field by field.
194
+ */
195
+ const lipoNameMatches = (reported, observed) => reported === observed ||
196
+ (observed === "arm64e" && /^arm64e\.[A-Za-z0-9_]+$/u.test(reported));
106
197
  const parseSliceKeyInteger = (value) => {
107
198
  if (value === undefined || !/^\d+$/u.test(value))
108
199
  return null;
@@ -7,6 +7,13 @@ import { ArtifactReaderFailure, } from "./ArtifactReader.js";
7
7
  import { DirectoryArtifactReader } from "./DirectoryArtifactReader.js";
8
8
  import { execFileOutput } from "../process/ExecFileOutput.js";
9
9
  const DETACH_TIMEOUT_MS = 120_000;
10
+ /**
11
+ * Waits before rechecking devices whose detach failed. A related device's
12
+ * later detach can eject one, `hdiutil info` can still list an ejected device
13
+ * briefly, and a volume can report busy just after it was read.
14
+ */
15
+ const DETACH_SETTLE_DELAYS_MS = [250, 500, 1000];
16
+ const delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
10
17
  const attachOutputSchema = z.object({
11
18
  "system-entities": z.array(z.object({
12
19
  "dev-entry": z.string().startsWith("/dev/"),
@@ -18,10 +25,12 @@ const infoOutputSchema = z.object({
18
25
  "system-entities": z.array(z.object({ "dev-entry": z.string() })),
19
26
  })),
20
27
  });
21
- const systemHost = {
28
+ const createSystemHost = (environment) => ({
29
+ delay,
22
30
  async run(arguments_, signal, options) {
23
31
  try {
24
32
  const { stdout, stderr } = await execFileOutput("/usr/bin/hdiutil", [...arguments_], {
33
+ env: environment,
25
34
  ...(options === undefined ? {} : { timeout: options.timeoutMs }),
26
35
  ...(signal === undefined ? {} : { signal }),
27
36
  });
@@ -41,7 +50,7 @@ const systemHost = {
41
50
  throw new ArtifactReaderFailure(commandFailureReason(cause, arguments_[0]), `hdiutil ${arguments_[0] ?? "operation"} failed: ${describeCommandFailure(cause, arguments_)}`, { cause });
42
51
  }
43
52
  },
44
- };
53
+ });
45
54
  /** Read-only macOS DMG adapter that owns attachment and reverse-order detach. */
46
55
  export class NativeDmgArtifactReader {
47
56
  path;
@@ -56,10 +65,10 @@ export class NativeDmgArtifactReader {
56
65
  this.host = host;
57
66
  }
58
67
  /** Verify and attach one image beneath an exclusively owned temporary root. */
59
- static async create(path, signal, host = systemHost) {
60
- if (process.platform !== "darwin" && host === systemHost)
68
+ static async create(path, environment, signal, host) {
69
+ if (process.platform !== "darwin" && host === undefined)
61
70
  throw new ArtifactReaderFailure("unavailable", "Native DMG traversal is available only on macOS");
62
- const reader = new NativeDmgArtifactReader(path, host);
71
+ const reader = new NativeDmgArtifactReader(path, host ?? createSystemHost(environment));
63
72
  await reader.attach(signal);
64
73
  return reader;
65
74
  }
@@ -80,28 +89,70 @@ export class NativeDmgArtifactReader {
80
89
  }
81
90
  async close() {
82
91
  let detachFailure;
92
+ let remainingDevices = [];
83
93
  for (const device of [...this.#devices].reverse()) {
84
- try {
85
- await runChecked(this.host, ["detach", device], undefined, {
86
- timeoutMs: DETACH_TIMEOUT_MS,
87
- });
88
- this.#provenance.push(command(["detach", device], ["mount"]));
94
+ const failure = await this.#detach(device);
95
+ if (failure !== undefined) {
96
+ remainingDevices.push(device);
97
+ detachFailure ??= failure;
89
98
  }
90
- catch (cause) {
91
- // Detaching a synthesized APFS container also ejects the image that
92
- // backs it, so a later whole disk of the same image may already be
93
- // gone. Only a device that is still attached is a cleanup failure.
94
- if (await this.#isAttached(device))
95
- detachFailure ??= cause;
99
+ }
100
+ // Detaching a synthesized APFS container also ejects the image that backs
101
+ // it, so a device whose own detach failed may be gone by the end of the
102
+ // pass, and hdiutil can list an ejected device or report busy briefly.
103
+ // Only a device that stays attached through every recheck is a failure.
104
+ for (const delayMs of DETACH_SETTLE_DELAYS_MS) {
105
+ if (remainingDevices.length === 0)
106
+ break;
107
+ await (this.host.delay ?? delay)(delayMs);
108
+ const stillAttached = [];
109
+ for (const device of remainingDevices) {
110
+ if (!(await this.#isAttached(device)))
111
+ continue;
112
+ const failure = await this.#detach(device);
113
+ if (failure !== undefined) {
114
+ stillAttached.push(device);
115
+ detachFailure = failure;
116
+ }
96
117
  }
118
+ remainingDevices = stillAttached;
97
119
  }
98
- this.#devices = [];
99
- if (this.#mountRoot !== undefined)
100
- await rm(this.#mountRoot, { recursive: true, force: true }).catch((cause) => {
120
+ if (remainingDevices.length === 0)
121
+ detachFailure = undefined;
122
+ this.#devices = remainingDevices.reverse();
123
+ if (this.#devices.length === 0 && this.#mountRoot !== undefined)
124
+ await rm(this.#mountRoot, { recursive: true, force: true }).then(() => {
125
+ this.#mountRoot = undefined;
126
+ this.#directory = undefined;
127
+ }, (cause) => {
101
128
  detachFailure ??= cause;
102
129
  });
103
130
  if (detachFailure !== undefined)
104
- throw new ArtifactReaderFailure("unavailable", "DMG detach or mount-root cleanup failed", { cause: detachFailure });
131
+ throw new ArtifactReaderFailure("unavailable", `DMG detach or mount-root cleanup failed for ${JSON.stringify(this.path)}: ${failureMessage(detachFailure)}`, {
132
+ cause: detachFailure,
133
+ cleanup: {
134
+ reason: failureMessage(detachFailure),
135
+ resources: [
136
+ ...this.#devices.map((device) => `DMG device ${device}`),
137
+ ...(this.#mountRoot === undefined
138
+ ? []
139
+ : [`DMG mount root ${this.#mountRoot}`]),
140
+ ],
141
+ },
142
+ });
143
+ }
144
+ /** Detach one device; return the failure only while it remains attached. */
145
+ async #detach(device) {
146
+ try {
147
+ await runChecked(this.host, ["detach", device], undefined, {
148
+ timeoutMs: DETACH_TIMEOUT_MS,
149
+ });
150
+ this.#provenance.push(command(["detach", device], ["mount"]));
151
+ return undefined;
152
+ }
153
+ catch (cause) {
154
+ return (await this.#isAttached(device)) ? cause : undefined;
155
+ }
105
156
  }
106
157
  /**
107
158
  * Report whether hdiutil still lists a device; unknown state counts as
@@ -169,11 +220,12 @@ export class NativeDmgArtifactReader {
169
220
  cleanupFailure = cleanupCause;
170
221
  }
171
222
  if (cleanupFailure !== undefined)
172
- throw new ArtifactReaderFailure("unavailable", "DMG attach failed and cleanup could not detach every device", { cause: new AggregateError([cause, cleanupFailure]) });
223
+ throw ArtifactReaderFailure.withCleanup(cause, ArtifactReaderFailure.cleanupObservation(cleanupFailure, `DMG mount root ${this.#mountRoot ?? this.path}`));
173
224
  throw cause;
174
225
  }
175
226
  }
176
227
  }
228
+ const failureMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
177
229
  const runChecked = async (host, arguments_, signal, options) => {
178
230
  let result;
179
231
  try {
@@ -129,7 +129,13 @@ export class SafeOutputTree {
129
129
  async rollback() {
130
130
  if (this.#published)
131
131
  return structuredClone(this.#cleanup);
132
- await rm(this.#outputRoot, { recursive: true, force: true });
132
+ let removalFailure;
133
+ try {
134
+ await rm(this.#outputRoot, { recursive: true, force: true });
135
+ }
136
+ catch (cause) {
137
+ removalFailure = cause;
138
+ }
133
139
  const absent = await isAbsent(this.#outputRoot);
134
140
  this.#cleanup = absent
135
141
  ? { status: "complete", residualPaths: [] }
@@ -138,7 +144,15 @@ export class SafeOutputTree {
138
144
  residualPaths: [basename(this.#outputRoot)],
139
145
  };
140
146
  if (!absent)
141
- throw new ArtifactReaderFailure("integrity", "Extraction output cleanup could not be verified");
147
+ throw new ArtifactReaderFailure("integrity", `Extraction output cleanup could not be verified${removalFailure === undefined ? "" : `: ${removalFailure instanceof Error ? removalFailure.message : String(removalFailure)}`}`, {
148
+ cause: removalFailure,
149
+ cleanup: {
150
+ reason: removalFailure instanceof Error
151
+ ? removalFailure.message
152
+ : "Extraction output root remains after rollback",
153
+ resources: [this.#outputRoot],
154
+ },
155
+ });
142
156
  return structuredClone(this.#cleanup);
143
157
  }
144
158
  async #prepareParent(relativePath) {
@@ -5,10 +5,12 @@ import { Reader, ZipReader } from "@zip.js/zip.js";
5
5
  import { ArtifactReaderFailure, } from "./ArtifactReader.js";
6
6
  class NodeFileReader extends Reader {
7
7
  path;
8
+ maximumReadBytes;
8
9
  #handle;
9
- constructor(path) {
10
+ constructor(path, maximumReadBytes) {
10
11
  super(path);
11
12
  this.path = path;
13
+ this.maximumReadBytes = maximumReadBytes;
12
14
  }
13
15
  async init() {
14
16
  this.#handle = await open(this.path, "r");
@@ -18,7 +20,11 @@ class NodeFileReader extends Reader {
18
20
  const handle = this.#handle;
19
21
  if (handle === undefined)
20
22
  throw new Error("ZIP reader is not initialized");
21
- const bytes = Buffer.alloc(Math.min(length, this.size - index));
23
+ const readBytes = Math.min(length, this.size - index);
24
+ if (this.maximumReadBytes !== undefined &&
25
+ readBytes > this.maximumReadBytes)
26
+ throw new ArtifactReaderFailure("limit", `ZIP metadata read requires ${readBytes} bytes, exceeding the ${this.maximumReadBytes}-byte read budget`);
27
+ const bytes = Buffer.alloc(readBytes);
22
28
  const read = await handle.read(bytes, 0, bytes.length, index);
23
29
  return bytes.subarray(0, read.bytesRead);
24
30
  }
@@ -33,9 +39,10 @@ export class ZipArtifactReader {
33
39
  #source;
34
40
  #reader;
35
41
  #entries = new Map();
36
- constructor(path, format) {
42
+ /** Optionally bound each metadata read before allocating its backing buffer. */
43
+ constructor(path, format, maximumMetadataReadBytes) {
37
44
  this.format = format;
38
- this.#source = new NodeFileReader(path);
45
+ this.#source = new NodeFileReader(path, maximumMetadataReadBytes);
39
46
  this.#reader = new ZipReader(this.#source, {
40
47
  checkSignature: true,
41
48
  checkOverlappingEntry: true,