rea-agents 6.3.0 → 6.4.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 (487) hide show
  1. package/README.md +7 -4
  2. package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
  3. package/bridge/ghidra/ReaGhidraBridge.java +597 -209
  4. package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
  5. package/dist/adb/AdbConfiguration.js +88 -0
  6. package/dist/adb/AdbDeviceOutput.js +186 -0
  7. package/dist/adb/AdbProvider.js +1190 -0
  8. package/dist/adb/AdbShellOutput.js +309 -0
  9. package/dist/android/AndroidTargetSnapshot.js +104 -22
  10. package/dist/android/JadxConfiguration.js +44 -24
  11. package/dist/android/JadxProvider.js +51 -19
  12. package/dist/apktool/ApktoolConfiguration.js +84 -0
  13. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  14. package/dist/apktool/ApktoolProvider.js +506 -0
  15. package/dist/application/AnalysisProvider.js +8 -2
  16. package/dist/application/AppBundleExecutable.js +27 -22
  17. package/dist/application/BinaryTargetResolver.js +22 -2
  18. package/dist/application/CapabilityInventory.js +11 -1
  19. package/dist/application/ClientConfigurationDocument.js +70 -0
  20. package/dist/application/ClientConfigurationFiles.js +91 -0
  21. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  22. package/dist/application/ClientRegistrationStatus.js +66 -31
  23. package/dist/application/DirectAnalysis.js +2 -2
  24. package/dist/application/DirectAnalysisCleanup.js +1 -1
  25. package/dist/application/DirectAnalysisStatus.js +1 -1
  26. package/dist/application/Doctor.js +5 -3
  27. package/dist/application/DoctorDiagnostics.js +1 -1
  28. package/dist/application/EvidenceBundleCommands.js +6 -12
  29. package/dist/application/GeminiClientSettings.js +139 -0
  30. package/dist/application/HermesClientHome.js +115 -0
  31. package/dist/application/HopperDownload.js +39 -0
  32. package/dist/application/InvestigationProviders.js +6 -0
  33. package/dist/application/JsonFiles.js +6 -5
  34. package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
  35. package/dist/application/LinuxHopper.js +4 -12
  36. package/dist/application/MacHopper.js +172 -149
  37. package/dist/application/MipsElfAbiFlags.js +140 -0
  38. package/dist/application/ProviderOperationExecution.js +31 -0
  39. package/dist/application/ReconstructionObligationCandidates.js +9 -3
  40. package/dist/application/ReferenceSourceImport.js +76 -29
  41. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  42. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  43. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  44. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  45. package/dist/application/RegularFileRead.js +93 -7
  46. package/dist/application/Setup.js +54 -6
  47. package/dist/application/SetupClientConfiguration.js +116 -16
  48. package/dist/application/SetupHost.js +102 -24
  49. package/dist/application/SetupPlan.js +5 -8
  50. package/dist/application/SetupSkill.js +58 -39
  51. package/dist/application/SupportedClients.js +290 -65
  52. package/dist/application/Uninstall.js +158 -10
  53. package/dist/application/UpdateMaintenance.js +17 -21
  54. package/dist/application/Utf8JsonInput.js +7 -0
  55. package/dist/application/WebScriptExportService.js +131 -65
  56. package/dist/application/WebSourceLocationService.js +3 -0
  57. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  58. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  59. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  60. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  61. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  62. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  63. package/dist/application/binary/BinarySession.js +2 -1
  64. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  65. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  66. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  67. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  68. package/dist/application/evm/EvmInterfaceService.js +3 -0
  69. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  70. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  71. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  72. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  73. package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
  74. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  75. package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
  76. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  77. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
  78. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  79. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
  80. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  81. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  82. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
  83. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  84. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
  85. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
  86. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  89. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
  90. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
  91. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
  92. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
  93. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
  94. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
  95. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
  96. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  97. package/dist/application/jeb/JebAnalysisService.js +13 -0
  98. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  99. package/dist/application/native/NativeUiActionTrace.js +16 -8
  100. package/dist/application/native/NativeValueTrace.js +23 -6
  101. package/dist/application/process/ProcessCli.js +25 -20
  102. package/dist/artifacts/ArtifactPaths.js +129 -8
  103. package/dist/artifacts/ArtifactProvider.js +20 -15
  104. package/dist/artifacts/ArtifactReader.js +23 -0
  105. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  106. package/dist/artifacts/AsarArtifactReader.js +176 -102
  107. package/dist/artifacts/AsarHeader.js +24 -0
  108. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  109. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  110. package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
  111. package/dist/artifacts/SafeOutputTree.js +245 -70
  112. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  113. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  114. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  115. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  116. package/dist/artifacts/ZipArtifactReader.js +77 -27
  117. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  118. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  119. package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
  120. package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
  121. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
  122. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  123. package/dist/artifacts/inventory/classify.js +75 -32
  124. package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
  125. package/dist/artifacts/inventory/reader.js +13 -5
  126. package/dist/artifacts/inventory/scanCanonical.js +62 -25
  127. package/dist/artifacts/inventory/scanReader.js +38 -11
  128. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
  129. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  130. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  131. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  132. package/dist/browser/CdpBrowserProvider.js +5 -0
  133. package/dist/browser/CdpCaptureDocuments.js +40 -6
  134. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  135. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  136. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  137. package/dist/browser/CdpCaptureEvents.js +4 -9
  138. package/dist/browser/CdpConnection.js +22 -5
  139. package/dist/browser/CdpPageCapture.js +1 -1
  140. package/dist/browser/CdpTargetSession.js +30 -34
  141. package/dist/browser/CdpWebMcpDiscovery.js +32 -10
  142. package/dist/browser/ElectronFileScope.js +99 -9
  143. package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
  144. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  145. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  146. package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
  147. package/dist/browser/PlaywrightScenarioSession.js +127 -54
  148. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  149. package/dist/browser/PngVisualDiff.js +198 -29
  150. package/dist/browser/WebSourceMapFetcher.js +3 -3
  151. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  152. package/dist/browser/assets/PublishWebScripts.js +75 -20
  153. package/dist/browser/assets/WebArtifactReads.js +23 -1
  154. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  155. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  156. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  157. package/dist/browser/history/HarCapture.js +14 -0
  158. package/dist/browser/history/HarCaptureProcess.js +2 -10
  159. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  160. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  161. package/dist/cli/adbCommands.js +337 -0
  162. package/dist/cli/analysisViewCommands.js +39 -1
  163. package/dist/cli/apktoolCommands.js +53 -0
  164. package/dist/cli/artifactCommands.js +8 -11
  165. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  166. package/dist/cli/browserAdvancedCommands.js +65 -36
  167. package/dist/cli/coreBinaryCommands.js +0 -5
  168. package/dist/cli/coreNativeCommands.js +1 -14
  169. package/dist/cli/electronCommands.js +6 -1
  170. package/dist/cli/evmCommands.js +13 -4
  171. package/dist/cli/firmwareCommands.js +7 -2
  172. package/dist/cli/javascriptApplicationAnalysis.js +17 -1
  173. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  174. package/dist/cli/jebCommands.js +99 -0
  175. package/dist/cli/jsonOutput.js +11 -4
  176. package/dist/cli/referenceSourceImportStatus.js +7 -0
  177. package/dist/cli/setupCommands.js +15 -3
  178. package/dist/cli/utilityCommands.js +66 -18
  179. package/dist/cli/webScriptCommands.js +20 -1
  180. package/dist/cli/webSourceLocationCommands.js +21 -9
  181. package/dist/cli.js +6 -0
  182. package/dist/cliBrowserScenarioCommands.js +2 -1
  183. package/dist/cliCommandNames.js +32 -0
  184. package/dist/cliJsonInput.js +2 -2
  185. package/dist/cliObservationOptions.js +3 -0
  186. package/dist/composition/adb.js +3 -0
  187. package/dist/composition/apktool.js +3 -0
  188. package/dist/composition/binaryDiagnostics.js +4 -0
  189. package/dist/composition/directAnalysis.js +12 -4
  190. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  191. package/dist/composition/jeb.js +6 -0
  192. package/dist/config/environment.js +10 -0
  193. package/dist/config/ghidraLanguageOverride.js +9 -0
  194. package/dist/config/mcpInputSchemaProfile.js +27 -0
  195. package/dist/config/parseConfig.js +28 -1
  196. package/dist/contracts/adb/adbToolContracts.js +353 -0
  197. package/dist/contracts/advertisedInputExamples.js +48 -0
  198. package/dist/contracts/analysisDetail.js +10 -0
  199. package/dist/contracts/analysisViewToolContracts.js +17 -2
  200. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  201. package/dist/contracts/artifactToolContracts.js +8 -5
  202. package/dist/contracts/browserToolContracts.js +1 -1
  203. package/dist/contracts/compactInputSchema.js +256 -0
  204. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  205. package/dist/contracts/inputSchemaPresentation.js +10 -10
  206. package/dist/contracts/javascript/electronToolContracts.js +15 -3
  207. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  208. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  209. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  210. package/dist/contracts/officialToolContracts.js +5 -5
  211. package/dist/contracts/sessionToolContracts.js +2 -2
  212. package/dist/contracts/sessionToolSchemas.js +6 -2
  213. package/dist/contracts/toolContractExamples.js +6 -0
  214. package/dist/contracts/toolContractTypes.js +3 -0
  215. package/dist/contracts/toolContracts.js +6 -0
  216. package/dist/contracts/toolEffects.js +167 -0
  217. package/dist/contracts/toolOutputSchemaGroups.js +5 -3
  218. package/dist/contracts/toolSchemaMetadata.js +82 -7
  219. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  220. package/dist/domain/analysisErrorCleanup.js +29 -0
  221. package/dist/domain/analysisErrorPresentation.js +18 -6
  222. package/dist/domain/analysisErrorProjection.js +4 -1
  223. package/dist/domain/analysisSnapshot.js +2 -1
  224. package/dist/domain/analysisView/analysisView.js +52 -2
  225. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  226. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  227. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  228. package/dist/domain/android/androidApplication.js +25 -20
  229. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  230. package/dist/domain/apple/appleApplication.js +40 -23
  231. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  232. package/dist/domain/apple/dyldPaths.js +9 -1
  233. package/dist/domain/apple/dylibResolution.js +2 -2
  234. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  235. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  236. package/dist/domain/artifactComparison.js +35 -7
  237. package/dist/domain/artifactGraph.js +5 -3
  238. package/dist/domain/artifactIdentity.js +30 -2
  239. package/dist/domain/artifactInspection.js +3 -43
  240. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  241. package/dist/domain/artifactInventoryEvidence.js +11 -12
  242. package/dist/domain/artifactPathSyntax.js +1 -1
  243. package/dist/domain/binaryTarget.js +16 -0
  244. package/dist/domain/binaryTargetTypes.js +8 -1
  245. package/dist/domain/browserObservationSchemas.js +8 -4
  246. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  247. package/dist/domain/compactStringIdentity.js +9 -0
  248. package/dist/domain/evidence.js +2 -1
  249. package/dist/domain/evidenceRecordSummary.js +144 -0
  250. package/dist/domain/inputIssueProjection.js +16 -1
  251. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
  252. package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
  253. package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
  254. package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
  255. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  256. package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
  257. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
  258. package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
  259. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  260. package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
  261. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
  262. package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
  263. package/dist/domain/javascript/javascriptAstValues.js +32 -0
  264. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  265. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  266. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
  267. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  268. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  269. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
  270. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
  271. package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
  272. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  273. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  274. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  275. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  276. package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
  277. package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
  278. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
  279. package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
  280. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
  281. package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
  282. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  283. package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
  284. package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
  285. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
  286. package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
  287. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
  288. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  289. package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
  290. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  291. package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
  292. package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
  293. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  294. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  295. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
  296. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  297. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  298. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  299. package/dist/domain/jeb/jebAnalysis.js +114 -0
  300. package/dist/domain/jsonShape.js +63 -52
  301. package/dist/domain/jsonValue.js +3 -0
  302. package/dist/domain/managed/managedApplicationGraph.js +37 -0
  303. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  304. package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
  305. package/dist/domain/managed/managedArtifact.js +1 -0
  306. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  307. package/dist/domain/native/nativeAotPe.js +1408 -0
  308. package/dist/domain/native/nativeInstruction.js +21 -0
  309. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  310. package/dist/domain/native/peResources.js +94 -0
  311. package/dist/domain/nativeConvention.js +33 -0
  312. package/dist/domain/process/processCapture.js +91 -1
  313. package/dist/domain/process/processCaptureExample.js +24 -0
  314. package/dist/domain/process/processCaptureValidation.js +79 -0
  315. package/dist/domain/process/processScenario.js +59 -7
  316. package/dist/domain/propertyListKeys.js +3 -1
  317. package/dist/domain/referenceSourceGraph.js +25 -16
  318. package/dist/domain/referenceSourceImportParsing.js +6 -3
  319. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  320. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  321. package/dist/domain/webBundleAnalyzerInspection.js +14 -2
  322. package/dist/domain/webCaptureDiff.js +102 -4
  323. package/dist/domain/webScriptExportError.js +10 -4
  324. package/dist/domain/webScriptExportPlan.js +7 -13
  325. package/dist/domain/zipPackageFormat.js +4 -1
  326. package/dist/domain/zodCollectionSteps.js +24 -0
  327. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  328. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  329. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  330. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  331. package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
  332. package/dist/dotnet/ManagedMemberRows.js +9 -4
  333. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  334. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  335. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  336. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  337. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  338. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  339. package/dist/dotnet/ManagedPeReader.js +41 -25
  340. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  341. package/dist/dotnet/ManagedStaticProvider.js +55 -24
  342. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  343. package/dist/evaluation/CodexAgentEval.js +43 -13
  344. package/dist/evm/EvmoleFailures.js +0 -2
  345. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  346. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  347. package/dist/filesystem/OwnedFileHandle.js +36 -0
  348. package/dist/filesystem/RegularFile.js +33 -1
  349. package/dist/filesystem/StableFileHash.js +46 -0
  350. package/dist/filesystem/readFileHandleChunks.js +26 -0
  351. package/dist/firmware/FirmwareCommand.js +25 -3
  352. package/dist/firmware/FirmwareFiles.js +23 -8
  353. package/dist/firmware/FirmwareProvider.js +156 -32
  354. package/dist/firmware/FirmwarePublication.js +24 -3
  355. package/dist/firmware/FirmwareRelease.js +1 -0
  356. package/dist/generatedPackageMetadata.js +2 -2
  357. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  358. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  359. package/dist/ghidra/GhidraClient.js +76 -4
  360. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  361. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  362. package/dist/ghidra/GhidraInstallation.js +1 -1
  363. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  364. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  365. package/dist/ghidra/GhidraLauncher.js +80 -39
  366. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  367. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  368. package/dist/ghidra/GhidraProvider.js +57 -9
  369. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  370. package/dist/ghidra/GhidraProviderClient.js +282 -21
  371. package/dist/ghidra/GhidraSessionValues.js +9 -2
  372. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  373. package/dist/hopper/HopperClient.js +15 -6
  374. package/dist/hopper/HopperMachOImage.js +2 -0
  375. package/dist/hopper/HopperProvider.js +13 -2
  376. package/dist/ida/IdaOperationRunner.js +8 -2
  377. package/dist/ida/IdaProvider.js +7 -0
  378. package/dist/ida/IdaSessionClient.js +3 -1
  379. package/dist/ida/IdaWorkspace.js +4 -2
  380. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  381. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  382. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  383. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  384. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  385. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  386. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  387. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  388. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  389. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  390. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  391. package/dist/javascript/recovery/WakaruReport.js +12 -7
  392. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  393. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  394. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  395. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  396. package/dist/jeb/JebMcpConnection.js +179 -0
  397. package/dist/jeb/JebMcpEndpoint.js +40 -0
  398. package/dist/jeb/JebProvider.js +299 -0
  399. package/dist/mcpDoctor.js +15 -6
  400. package/dist/native/AppleDispatchCoverage.js +25 -12
  401. package/dist/native/AppleDispatchMetadata.js +14 -7
  402. package/dist/native/AppleMachoFixups.js +71 -15
  403. package/dist/native/AppleMachoSelection.js +23 -3
  404. package/dist/native/NativeMacOSProvider.js +91 -16
  405. package/dist/native/NativeMachoInspection.js +11 -7
  406. package/dist/native/NativeUiHelperRuntime.js +6 -1
  407. package/dist/native/NativeUiObservation.js +4 -3
  408. package/dist/native/pe/PeResourceLayout.js +120 -0
  409. package/dist/native/pe/PeResourceParser.js +286 -0
  410. package/dist/native/pe/PeResourcesProvider.js +63 -0
  411. package/dist/process/BoundedFileBytes.js +30 -7
  412. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  413. package/dist/process/OwnedCommand.js +4 -3
  414. package/dist/process/ProcessOwnership.js +104 -112
  415. package/dist/process/ProcessOwnershipObservation.js +96 -39
  416. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  417. package/dist/process/ProcessRunTokenObservations.js +48 -0
  418. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  419. package/dist/process/ProviderProcess.js +4 -3
  420. package/dist/process/capture/FilesystemSnapshot.js +28 -4
  421. package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
  422. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  423. package/dist/process/capture/ProcessHarness.js +194 -26
  424. package/dist/process/capture/ProcessNormalization.js +3 -1
  425. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  426. package/dist/process/capture/TerminalRenderer.js +24 -7
  427. package/dist/reference/ReferenceSourceReader.js +22 -5
  428. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  429. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  430. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  431. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  432. package/dist/server/EvidenceMcpServer.js +36 -1
  433. package/dist/server/admittedToolOperation.js +9 -0
  434. package/dist/server/contractToolHandler.js +21 -0
  435. package/dist/server/createServer.js +97 -25
  436. package/dist/server/registerAdbTools.js +36 -0
  437. package/dist/server/registerAnalysisViewTool.js +4 -9
  438. package/dist/server/registerAndroidTools.js +3 -12
  439. package/dist/server/registerApktoolTools.js +14 -0
  440. package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
  441. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  442. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  443. package/dist/server/registerApplicationTools/coverage.js +3 -2
  444. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  445. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  446. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  447. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  448. package/dist/server/registerArtifactComparisonTool.js +5 -2
  449. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  450. package/dist/server/registerBrowserScenarioTool.js +10 -7
  451. package/dist/server/registerBrowserTools.js +12 -9
  452. package/dist/server/registerBundleComparisonTool.js +16 -2
  453. package/dist/server/registerCloseLifecycleTool.js +32 -3
  454. package/dist/server/registerElectronTools.js +28 -10
  455. package/dist/server/registerEvmTools.js +4 -9
  456. package/dist/server/registerFirmwareTools.js +3 -11
  457. package/dist/server/registerFunctionComparisonTool.js +5 -2
  458. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  459. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  460. package/dist/server/registerJebTools.js +16 -0
  461. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  462. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  463. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  464. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  465. package/dist/server/registerPeResourcesTool.js +9 -0
  466. package/dist/server/registerProcessComparisonTool.js +5 -2
  467. package/dist/server/registerRecordedCrashTools.js +4 -9
  468. package/dist/server/registerSessionRecordTools.js +2 -1
  469. package/dist/server/registerSessionTools.js +49 -18
  470. package/dist/server/registerWebModuleTool.js +4 -9
  471. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  472. package/dist/server/registerWebRuntimeTools.js +6 -5
  473. package/dist/server/registerWebScriptTool.js +6 -3
  474. package/dist/server/registerWebSourceLocationTool.js +4 -9
  475. package/dist/server/toolResult.js +21 -2
  476. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  477. package/install.sh +7 -4
  478. package/licenses/nativeaot-parser-MIT.txt +28 -0
  479. package/native/windows/build/manifest.json +2 -2
  480. package/native/windows/build/rea-windows-x64.node +0 -0
  481. package/package.json +33 -5
  482. package/scripts/rea.mjs +16 -1
  483. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  484. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  485. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  486. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  487. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
@@ -1,20 +1,54 @@
1
- import { open } from "node:fs/promises";
2
1
  import { PassThrough } from "node:stream";
3
2
  import { once } from "node:events";
4
3
  import { Reader, ZipReader } from "@zip.js/zip.js";
5
- import { ArtifactReaderFailure, } from "./ArtifactReader.js";
4
+ import { ArtifactReaderFailure, copyArtifactEntry, sameArtifactEntry, } from "./ArtifactReader.js";
5
+ import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js";
6
+ import { NonRegularFileReadError, RegularFileAdmissionFailure, openRegularFile, sameRegularFileState, } from "../filesystem/RegularFile.js";
6
7
  class NodeFileReader extends Reader {
7
8
  path;
8
9
  maximumReadBytes;
10
+ admitted;
9
11
  #handle;
10
- constructor(path, maximumReadBytes) {
12
+ #owner;
13
+ #initPromise;
14
+ #ownsHandle;
15
+ constructor(path, maximumReadBytes, admitted) {
11
16
  super(path);
12
17
  this.path = path;
13
18
  this.maximumReadBytes = maximumReadBytes;
19
+ this.admitted = admitted;
20
+ this.#ownsHandle = admitted === undefined;
14
21
  }
15
- async init() {
16
- this.#handle = await open(this.path, "r");
17
- this.size = (await this.#handle.stat()).size;
22
+ init() {
23
+ this.#initPromise ??= this.#initialize();
24
+ return this.#initPromise;
25
+ }
26
+ async #initialize() {
27
+ try {
28
+ const handle = this.admitted?.handle ??
29
+ (await openRegularFile(this.path, { symlinks: "reject" }));
30
+ this.#handle = handle;
31
+ if (this.#ownsHandle)
32
+ this.#owner = new OwnedFileHandle(handle);
33
+ }
34
+ catch (cause) {
35
+ if (cause instanceof RegularFileAdmissionFailure) {
36
+ this.#owner = cause.owner;
37
+ const primary = cause.cause instanceof NonRegularFileReadError
38
+ ? new ArtifactReaderFailure("format", `ZIP source is not a regular file: ${this.path}`, { cause: cause.cause })
39
+ : cause.cause;
40
+ throw ArtifactReaderFailure.withCleanup(primary, ArtifactReaderFailure.cleanupObservation(cause.cleanupCause, this.path));
41
+ }
42
+ if (cause instanceof NonRegularFileReadError)
43
+ throw new ArtifactReaderFailure("format", `ZIP source is not a regular file: ${this.path}`, { cause });
44
+ throw cause;
45
+ }
46
+ const metadata = await this.#handle.stat();
47
+ if (!metadata.isFile() ||
48
+ (this.admitted !== undefined &&
49
+ !sameRegularFileState(this.admitted.initial, metadata)))
50
+ throw new ArtifactReaderFailure("integrity", `ZIP source identity changed before reading: ${this.path}`);
51
+ this.size = metadata.size;
18
52
  }
19
53
  async readUint8Array(index, length) {
20
54
  const handle = this.#handle;
@@ -29,7 +63,13 @@ class NodeFileReader extends Reader {
29
63
  return bytes.subarray(0, read.bytesRead);
30
64
  }
31
65
  async closeHandle() {
32
- await this.#handle?.close();
66
+ if (!this.#ownsHandle)
67
+ return;
68
+ await this.#initPromise?.catch(() => undefined);
69
+ if (this.#owner === undefined)
70
+ return;
71
+ await this.#owner.close();
72
+ this.#owner = undefined;
33
73
  this.#handle = undefined;
34
74
  }
35
75
  }
@@ -40,9 +80,9 @@ export class ZipArtifactReader {
40
80
  #reader;
41
81
  #entries = new Map();
42
82
  /** Optionally bound each metadata read before allocating its backing buffer. */
43
- constructor(path, format, maximumMetadataReadBytes) {
83
+ constructor(path, format, maximumMetadataReadBytes, admitted) {
44
84
  this.format = format;
45
- this.#source = new NodeFileReader(path, maximumMetadataReadBytes);
85
+ this.#source = new NodeFileReader(path, maximumMetadataReadBytes, admitted);
46
86
  this.#reader = new ZipReader(this.#source, {
47
87
  checkSignature: true,
48
88
  checkOverlappingEntry: true,
@@ -54,31 +94,25 @@ export class ZipArtifactReader {
54
94
  async *entries(signal) {
55
95
  for await (const entry of this.#reader.getEntriesGenerator()) {
56
96
  abortIfNeeded(signal);
57
- this.#entries.set(entry.filename, entry);
58
- const symlink = isSymlink(entry);
59
- yield {
60
- path: entry.filename,
61
- kind: entry.directory ? "directory" : symlink ? "symlink" : "file",
62
- declaredSize: entry.directory ? null : entry.uncompressedSize,
63
- compressedSize: entry.directory ? null : entry.compressedSize,
64
- executable: entry.executable,
65
- encrypted: entry.encrypted,
66
- byteOffset: null,
67
- declaredSha256: null,
68
- unpacked: false,
69
- limitations: symlink ? ["Archive symlink target was not read."] : [],
70
- adapterKey: entry.filename,
71
- };
97
+ const metadata = projectZipEntry(entry);
98
+ this.#entries.set(entry.filename, {
99
+ source: entry,
100
+ metadata: copyArtifactEntry(metadata),
101
+ });
102
+ yield metadata;
72
103
  }
73
104
  }
74
105
  open(entry, signal) {
75
106
  abortIfNeeded(signal);
76
107
  const stored = this.#entries.get(entry.adapterKey);
77
- if (stored === undefined || stored.directory || isSymlink(stored))
108
+ if (stored === undefined || !sameArtifactEntry(entry, stored.metadata))
109
+ return Promise.reject(new ArtifactReaderFailure("integrity", "ZIP entry metadata does not match this reader's inventory"));
110
+ const source = stored.source;
111
+ if (source.directory || isSymlink(source))
78
112
  return Promise.reject(new ArtifactReaderFailure("format", "ZIP entry is not a regular file"));
79
- if (stored.encrypted)
113
+ if (source.encrypted)
80
114
  return Promise.reject(new ArtifactReaderFailure("unavailable", "Encrypted ZIP entry is unsupported"));
81
- return Promise.resolve(extractStream(stored, signal));
115
+ return Promise.resolve(extractStream(source, signal));
82
116
  }
83
117
  async close() {
84
118
  // best-effort cleanup: zip-reader close must not mask prior extraction state.
@@ -89,6 +123,22 @@ export class ZipArtifactReader {
89
123
  return [];
90
124
  }
91
125
  }
126
+ const projectZipEntry = (entry) => {
127
+ const symlink = isSymlink(entry);
128
+ return {
129
+ path: entry.filename,
130
+ kind: entry.directory ? "directory" : symlink ? "symlink" : "file",
131
+ declaredSize: entry.directory ? null : entry.uncompressedSize,
132
+ compressedSize: entry.directory ? null : entry.compressedSize,
133
+ executable: entry.executable,
134
+ encrypted: entry.encrypted,
135
+ byteOffset: null,
136
+ declaredSha256: null,
137
+ unpacked: false,
138
+ limitations: symlink ? ["Archive symlink target was not read."] : [],
139
+ adapterKey: entry.filename,
140
+ };
141
+ };
92
142
  const extractStream = (entry, signal) => {
93
143
  const output = new PassThrough();
94
144
  const controller = new AbortController();
@@ -4,10 +4,11 @@ import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
4
4
  import { projectPlistValue } from "../../domain/apple/plistValue.js";
5
5
  import { omittedPrototypeKeysLimitation, parseXmlPropertyList, } from "../../domain/propertyListKeys.js";
6
6
  import { decodeNibArchive } from "./NibArchive.js";
7
- import { estimatePropertyListDecodeBytes, InterfaceBuilderDecodeBudget, InterfaceBuilderDecodeBudgetExceeded, } from "./InterfaceBuilderDecodeBudget.js";
7
+ import { preflightPropertyListDecode, InterfaceBuilderDecodeBudget, InterfaceBuilderDecodeBudgetExceeded, } from "./InterfaceBuilderDecodeBudget.js";
8
8
  import { buildInterfaceBuilderAnalysis, interfaceBuilderLimitsSchema, } from "../../domain/apple/interfaceBuilderGraph.js";
9
9
  import { mergeNibHierarchies, projectNibViewHierarchy, } from "./NibViewHierarchy.js";
10
10
  import { jsonValueSchema } from "../../domain/jsonValue.js";
11
+ import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
11
12
  import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
12
13
  const MAX_AGGREGATE_INPUT_BYTES = 32 * 1024 * 1024;
13
14
  const MAX_AGGREGATE_DECODE_BYTES = 256 * 1024 * 1024;
@@ -24,7 +25,6 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
24
25
  const prototypeKeyOmissions = new Map();
25
26
  let omitted = 0;
26
27
  let attempted = 0;
27
- let candidates = 0;
28
28
  let aggregateInputBytes = 0;
29
29
  const decodeBudget = new InterfaceBuilderDecodeBudget(MAX_AGGREGATE_DECODE_BYTES);
30
30
  const recordOmittedArchive = (path, reason) => {
@@ -34,15 +34,12 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
34
34
  unreportedOmittedArchives += 1;
35
35
  };
36
36
  try {
37
- for await (const entry of reader.entries(input.signal)) {
38
- if (entry.kind !== "file" || !isInterfaceBuilderArchive(entry.path))
39
- continue;
40
- candidates += 1;
41
- if (candidates > limits.max_documents) {
42
- omitted += 1;
43
- recordOmittedArchive(entry.path, "max_documents");
44
- continue;
45
- }
37
+ const selection = await selectInterfaceBuilderCandidates(reader, input.signal, limits.max_documents);
38
+ omitted = selection.omitted;
39
+ for (const entry of selection.omittedSamples)
40
+ recordOmittedArchive(entry.path, "max_documents");
41
+ unreportedOmittedArchives += selection.unreportedOmitted;
42
+ for (const entry of selection.selected) {
46
43
  try {
47
44
  const remainingInputBytes = MAX_AGGREGATE_INPUT_BYTES - aggregateInputBytes;
48
45
  if (entry.declaredSize !== null &&
@@ -57,6 +54,7 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
57
54
  const isNibArchive = bytes.subarray(0, 10).toString("ascii") === "NIBArchive";
58
55
  let nib = null;
59
56
  let xmlText;
57
+ let binaryPrototypeKeyObserved = false;
60
58
  if (isNibArchive) {
61
59
  const documentBudget = new InterfaceBuilderDecodeBudget(decodeBudget.remainingBytes);
62
60
  nib = projectNibArchive(decodeNibArchive(bytes, documentBudget), documentBudget, limits.max_objects);
@@ -65,15 +63,17 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
65
63
  else {
66
64
  if (bytes.subarray(0, 8).toString("ascii") !== "bplist00")
67
65
  xmlText = decodeXmlPlistText(bytes);
68
- const decodedReservation = estimatePropertyListDecodeBytes(bytes, decodeBudget.remainingBytes, xmlText);
69
- decodeBudget.reserve(decodedReservation, "plist representation exceeds the aggregate Interface Builder decode budget");
66
+ const decodedReservation = preflightPropertyListDecode(bytes, decodeBudget.remainingBytes, xmlText);
67
+ decodeBudget.reserve(decodedReservation.estimatedBytes, "plist representation exceeds the aggregate Interface Builder decode budget");
68
+ binaryPrototypeKeyObserved =
69
+ decodedReservation.binaryPrototypeKeyObserved;
70
70
  }
71
71
  const { value: raw, omittedPrototypeKeys } = nib === null
72
- ? decodePlist(bytes, xmlText)
72
+ ? decodePlist(bytes, xmlText, binaryPrototypeKeyObserved)
73
73
  : { value: nib.raw, omittedPrototypeKeys: 0 };
74
74
  if (nib !== null && nib.omitted > 0)
75
75
  incompleteHierarchies.set(entry.path, nib.omitted);
76
- if (omittedPrototypeKeys > 0)
76
+ if (omittedPrototypeKeys !== 0)
77
77
  prototypeKeyOmissions.set(entry.path, omittedPrototypeKeys);
78
78
  const documentHash = createHash("sha256").update(bytes).digest("hex");
79
79
  documents.push({
@@ -116,6 +116,42 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
116
116
  omitted,
117
117
  });
118
118
  };
119
+ /** Select lexically earliest document paths independent of host traversal order. */
120
+ const selectInterfaceBuilderCandidates = async (reader, signal, maximumDocuments) => {
121
+ const capacity = maximumDocuments + MAX_REPORTED_OMITTED_ARCHIVES;
122
+ const candidates = [];
123
+ let total = 0;
124
+ for await (const entry of reader.entries(signal)) {
125
+ if (entry.kind !== "file" || !isInterfaceBuilderArchive(entry.path))
126
+ continue;
127
+ total += 1;
128
+ retainCandidate(candidates, entry, capacity);
129
+ }
130
+ const omittedSamples = candidates.slice(maximumDocuments, capacity);
131
+ return {
132
+ selected: candidates.slice(0, maximumDocuments),
133
+ omittedSamples,
134
+ omitted: Math.max(0, total - maximumDocuments),
135
+ unreportedOmitted: Math.max(0, total - maximumDocuments - omittedSamples.length),
136
+ };
137
+ };
138
+ /** Keep the earliest bounded path set; directory iteration order is host-defined. */
139
+ const retainCandidate = (candidates, entry, maximum) => {
140
+ let low = 0;
141
+ let high = candidates.length;
142
+ while (low < high) {
143
+ const middle = Math.floor((low + high) / 2);
144
+ const existing = candidates[middle];
145
+ if (existing !== undefined &&
146
+ compareUnicodeCodePoints(existing.path, entry.path) < 0)
147
+ low = middle + 1;
148
+ else
149
+ high = middle;
150
+ }
151
+ candidates.splice(low, 0, entry);
152
+ if (candidates.length > maximum)
153
+ candidates.pop();
154
+ };
119
155
  const finalizeHierarchyCoverage = (result, counts) => {
120
156
  const { incompleteHierarchies, prototypeKeyOmissions, invalid, omittedArchives, unreportedOmittedArchives, } = counts;
121
157
  const archiveDecodePartial = invalid.length > 0 ||
@@ -452,9 +488,13 @@ const readEntry = async (reader, entry, signal, maxInputBytes = MAX_AGGREGATE_IN
452
488
  return Buffer.concat(chunks, length);
453
489
  };
454
490
  /** Project decoded plist data and dates while retaining omitted-key coverage. */
455
- const decodePlist = (bytes, xmlText) => {
456
- const { value, omittedPrototypeKeys } = bytes.subarray(0, 8).toString("ascii") === "bplist00"
457
- ? { value: parseBinary(bytes), omittedPrototypeKeys: 0 }
491
+ const decodePlist = (bytes, xmlText, binaryPrototypeKeyObserved) => {
492
+ const binary = bytes.subarray(0, 8).toString("ascii") === "bplist00";
493
+ const { value, omittedPrototypeKeys } = binary
494
+ ? {
495
+ value: parseBinary(bytes),
496
+ omittedPrototypeKeys: binaryPrototypeKeyObserved ? null : 0,
497
+ }
458
498
  : parseXmlPropertyList(xmlText ?? decodeXmlPlistText(bytes));
459
499
  return { value: projectPlistValue(value).value, omittedPrototypeKeys };
460
500
  };
@@ -58,13 +58,16 @@ export class InterfaceBuilderDecodeBudget {
58
58
  }
59
59
  }
60
60
  /** Preflight the representation created by the pinned plist decoder. */
61
- export const estimatePropertyListDecodeBytes = (bytes, maxBytes, xmlText) => {
62
- const estimate = bytes.subarray(0, 8).toString("ascii") === "bplist00"
61
+ export const preflightPropertyListDecode = (bytes, maxBytes, xmlText) => {
62
+ const expansion = bytes.subarray(0, 8).toString("ascii") === "bplist00"
63
63
  ? estimateBinaryPlistExpansion(bytes, maxBytes)
64
- : estimateXmlPlistExpansion(bytes, maxBytes, xmlText);
65
- if (estimate > maxBytes)
64
+ : {
65
+ estimatedBytes: estimateXmlPlistExpansion(bytes, maxBytes, xmlText),
66
+ binaryPrototypeKeyObserved: false,
67
+ };
68
+ if (expansion.estimatedBytes > maxBytes)
66
69
  throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "plist representation exceeds the aggregate Interface Builder decode budget");
67
- return estimate;
70
+ return expansion;
68
71
  };
69
72
  const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
70
73
  const xml = xmlText ?? decodeXmlPlistText(bytes);
@@ -94,8 +97,14 @@ const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
94
97
  }
95
98
  return decodedSourceBytes * 2 + elementCount * 128;
96
99
  };
97
- /** Count every expanded binary-plist reference before calling plist.parseBinary. */
98
- const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
100
+ const interfaceBuilderBudgetFailure = (_kind, message) => new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", message);
101
+ const PROTOTYPE_KEY = "__proto__";
102
+ /**
103
+ * Count every expanded binary-plist reference before calling plist.parseBinary,
104
+ * which recurses on each reference and copies shared containers. Malformed
105
+ * structure throws TypeError; budget, depth, and cycle failures use `fail`.
106
+ */
107
+ export const estimateBinaryPlistExpansion = (bytes, maxBytes, { budget = "the aggregate Interface Builder decode budget", fail = interfaceBuilderBudgetFailure, bounds = "strict", } = {}) => {
99
108
  if (bytes.length < 40)
100
109
  throw new TypeError("binary plist trailer is truncated");
101
110
  const trailer = bytes.length - 32;
@@ -115,19 +124,20 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
115
124
  const objectCount = readInteger(trailer + 8, 8);
116
125
  const topObject = readInteger(trailer + 16, 8);
117
126
  const offsetTable = readInteger(trailer + 24, 8);
127
+ const tableEnd = bounds === "strict" ? trailer : bytes.length;
128
+ const objectsEnd = bounds === "strict" ? offsetTable : bytes.length;
118
129
  if (objectCount < 1 ||
119
130
  topObject < 0 ||
120
131
  topObject >= objectCount ||
121
132
  offsetTable < 8 ||
122
- offsetTable + objectCount * offsetSize > trailer)
133
+ offsetTable + objectCount * offsetSize > tableEnd)
123
134
  throw new TypeError("binary plist trailer or object table is invalid");
124
135
  let estimate = bytes.length * 2 + objectCount * 16;
136
+ let binaryPrototypeKeyObserved = false;
125
137
  if (estimate > maxBytes)
126
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist object table exceeds the aggregate Interface Builder decode budget");
138
+ throw fail("expansion", `binary plist object table exceeds ${budget}`);
127
139
  const active = new Set();
128
- const pending = [
129
- { object: topObject, depth: 0, exit: false },
130
- ];
140
+ const pending = [{ object: topObject, depth: 0, exit: false, dictionaryKey: false }];
131
141
  let pendingObjectCount = 1;
132
142
  while (pending.length > 0) {
133
143
  const entry = pending.pop();
@@ -139,14 +149,14 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
139
149
  }
140
150
  pendingObjectCount -= 1;
141
151
  if (entry.depth > 128)
142
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist nesting exceeds the aggregate Interface Builder decode budget");
152
+ throw fail("depth", `binary plist nesting exceeds ${budget}`);
143
153
  if (active.has(entry.object))
144
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference cycle exceeds the aggregate Interface Builder decode budget");
154
+ throw fail("cycle", `binary plist reference cycle exceeds ${budget}`);
145
155
  estimate += 96;
146
156
  if (estimate > maxBytes)
147
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
157
+ throw fail("expansion", `binary plist reference expansion exceeds ${budget}`);
148
158
  const offset = readInteger(offsetTable + entry.object * offsetSize, offsetSize);
149
- if (offset < 8 || offset >= offsetTable)
159
+ if (offset < 8 || offset >= objectsEnd)
150
160
  throw new TypeError("binary plist object offset is invalid");
151
161
  const marker = bytes[offset] ?? 0;
152
162
  const type = marker >> 4;
@@ -160,36 +170,64 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
160
170
  const integerSize = 1 << (extMarker & 0x0f);
161
171
  size = readInteger(cursor, integerSize);
162
172
  cursor += integerSize;
163
- if (size < 0 || cursor > offsetTable)
173
+ if (size < 0 || cursor > objectsEnd)
164
174
  throw new TypeError("binary plist extended object size is invalid");
165
175
  }
166
176
  if (type === 4 || type === 5 || type === 6) {
167
177
  const byteLength = type === 6 ? size * 2 : size;
168
- if (cursor + byteLength > offsetTable)
178
+ if (cursor + byteLength > objectsEnd)
169
179
  throw new TypeError("binary plist scalar object is truncated");
180
+ if (!binaryPrototypeKeyObserved &&
181
+ entry.dictionaryKey &&
182
+ (type === 5 || type === 6) &&
183
+ size === PROTOTYPE_KEY.length) {
184
+ let matches = true;
185
+ for (let index = 0; index < PROTOTYPE_KEY.length; index += 1) {
186
+ const codeUnit = type === 5
187
+ ? (bytes[cursor + index] ?? 0)
188
+ : ((bytes[cursor + index * 2] ?? 0) << 8) |
189
+ (bytes[cursor + index * 2 + 1] ?? 0);
190
+ if (codeUnit !== PROTOTYPE_KEY.charCodeAt(index)) {
191
+ matches = false;
192
+ break;
193
+ }
194
+ }
195
+ if (matches)
196
+ binaryPrototypeKeyObserved = true;
197
+ }
170
198
  estimate += type === 4 ? size + 4 * Math.ceil(size / 3) : byteLength * 2;
171
199
  if (estimate > maxBytes)
172
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist scalar expansion exceeds the aggregate Interface Builder decode budget");
200
+ throw fail("expansion", `binary plist scalar expansion exceeds ${budget}`);
173
201
  continue;
174
202
  }
175
203
  if (type !== 10 && type !== 13)
176
204
  continue;
177
205
  const childCount = type === 13 ? size * 2 : size;
178
206
  const refsEnd = cursor + childCount * referenceSize;
179
- if (!Number.isSafeInteger(refsEnd) || refsEnd > offsetTable)
207
+ if (!Number.isSafeInteger(refsEnd) || refsEnd > objectsEnd)
180
208
  throw new TypeError("binary plist reference table is truncated");
181
209
  const availableNodes = Math.floor((maxBytes - estimate) / 96);
182
210
  if (childCount > availableNodes - pendingObjectCount)
183
- throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
211
+ throw fail("expansion", `binary plist reference expansion exceeds ${budget}`);
184
212
  active.add(entry.object);
185
- pending.push({ object: entry.object, depth: entry.depth, exit: true });
213
+ pending.push({
214
+ object: entry.object,
215
+ depth: entry.depth,
216
+ exit: true,
217
+ dictionaryKey: false,
218
+ });
186
219
  for (let index = childCount - 1; index >= 0; index -= 1) {
187
220
  const reference = readInteger(cursor + index * referenceSize, referenceSize);
188
221
  if (reference < 0 || reference >= objectCount)
189
222
  throw new TypeError("binary plist reference is invalid");
190
- pending.push({ object: reference, depth: entry.depth + 1, exit: false });
223
+ pending.push({
224
+ object: reference,
225
+ depth: entry.depth + 1,
226
+ exit: false,
227
+ dictionaryKey: type === 13 && index < size,
228
+ });
191
229
  }
192
230
  pendingObjectCount += childCount;
193
231
  }
194
- return estimate;
232
+ return { estimatedBytes: estimate, binaryPrototypeKeyObserved };
195
233
  };
@@ -11,7 +11,10 @@ import { KeyedArchiveKindError, keyedArchiveInputSchema, keyedArchiveResultSchem
11
11
  import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
12
12
  import { ArtifactReaderFailure } from "../ArtifactReader.js";
13
13
  import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
14
+ import { estimateBinaryPlistExpansion } from "./InterfaceBuilderDecodeBudget.js";
14
15
  const MAX_BYTES = 64 * 1024 * 1024;
16
+ /** Decoded representation budget, the same 8:1 ratio Interface Builder uses. */
17
+ const MAX_DECODE_BYTES = 8 * MAX_BYTES;
15
18
  /** Parse inert plist bytes, preserving data and dates with explicit typed values. */
16
19
  export const decodeKeyedArchiveBytes = (bytes, selection) => {
17
20
  if (bytes.length > MAX_BYTES)
@@ -20,8 +23,25 @@ export const decodeKeyedArchiveBytes = (bytes, selection) => {
20
23
  throw new KeyedArchiveKindError("Selected file is a compiled NIBArchive, not a Foundation plist archive; decode it with decode_interface_builder", "nib-archive");
21
24
  const binary = bytes.subarray(0, 8).toString("ascii") === "bplist00";
22
25
  const xmlText = binary ? undefined : decodeXmlPlistText(bytes);
23
- const parsed = binary
24
- ? { value: parseBinary(bytes), omittedPrototypeKeys: 0 }
26
+ // plist.parseBinary recurses on every object reference and copies shared
27
+ // containers, so a few hundred bytes can exhaust memory or the stack.
28
+ // RangeError reports a resource limit; a reference cycle is malformed.
29
+ const binaryExpansion = binary
30
+ ? estimateBinaryPlistExpansion(bytes, MAX_DECODE_BYTES, {
31
+ budget: "the keyed archive decode budget",
32
+ fail: (kind, message) => kind === "cycle"
33
+ ? new TypeError("binary plist object references form a cycle, which a property list cannot represent")
34
+ : new RangeError(message),
35
+ bounds: "decoder",
36
+ })
37
+ : undefined;
38
+ const parsed = binaryExpansion !== undefined
39
+ ? {
40
+ value: parseBinary(bytes),
41
+ omittedPrototypeKeys: binaryExpansion.binaryPrototypeKeyObserved
42
+ ? null
43
+ : 0,
44
+ }
25
45
  : parseXmlPropertyList(xmlText ?? "");
26
46
  const { value: plistValue, unknownRealCount } = projectPlistValue(parsed.value);
27
47
  const graph = projectKeyedArchive(plistValue, selection);
@@ -82,21 +102,20 @@ export const inspectBundleKeyedArchive = async (input) => {
82
102
  try {
83
103
  // Match inventory spelling while retaining the raw path for I/O and evidence.
84
104
  const wanted = selected.path.normalize("NFC");
85
- const matches = [];
86
- for await (const entry of reader.entries(input.signal)) {
87
- if (entry.path.normalize("NFC") !== wanted)
105
+ let entry;
106
+ for await (const candidate of reader.entries(input.signal, (directory) => wanted.startsWith(`${directory.normalize("NFC")}/`))) {
107
+ if (candidate.path.normalize("NFC") !== wanted)
88
108
  continue;
89
- matches.push(entry);
109
+ if (candidate.kind !== "file")
110
+ throw archivePathError("invalid_value", `Archive path selects a ${candidate.kind}, not a regular file: ${selected.path}`);
111
+ if ((candidate.declaredSize ?? 0) > MAX_BYTES)
112
+ throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
113
+ if (entry !== undefined)
114
+ throw archivePathError("invalid_value", `Archive path matches multiple Unicode-equivalent bundle entries; selection is ambiguous: ${selected.path}`);
115
+ entry = candidate;
90
116
  }
91
- if (matches.length > 1)
92
- throw archivePathError("invalid_value", `Archive path matches ${String(matches.length)} Unicode-equivalent bundle entries; selection is ambiguous: ${selected.path}`);
93
- const entry = matches[0];
94
117
  if (entry === undefined)
95
118
  throw archivePathError("invalid_value", `No regular file exists at ${selected.path} in the active app bundle.`);
96
- if (entry.kind !== "file")
97
- throw archivePathError("invalid_value", `Archive path selects a ${entry.kind}, not a regular file: ${selected.path}`);
98
- if ((entry.declaredSize ?? 0) > MAX_BYTES)
99
- throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
100
119
  const stream = await reader.open(entry, input.signal);
101
120
  const chunks = [];
102
121
  let size = 0;