rea-agents 5.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/README.md +168 -655
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +173 -47
  4. package/bridge/hopper_bridge.py +310 -128
  5. package/bridge/mitmproxy/capture.py +208 -0
  6. package/bridge/native/rea_lldb_tracer.py +839 -0
  7. package/bridge/process/ProcessRunTokenReader.swift +297 -0
  8. package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
  9. package/bridge/pwndbg/core_context.py +101 -0
  10. package/bridge/pwndbg/launch.py +39 -0
  11. package/bridge/pwndbg/launch_impl.py +34 -0
  12. package/bridge/pwntools/decoder_runtime.py +59 -0
  13. package/bridge/pwntools/layout.py +39 -0
  14. package/bridge/pwntools/layout_impl.py +309 -0
  15. package/bridge/pwntools/recorded_crash.py +39 -0
  16. package/bridge/pwntools/recorded_crash_impl.py +147 -0
  17. package/dist/android/JadxConfiguration.js +196 -33
  18. package/dist/android/JadxMcpTransport.js +4 -0
  19. package/dist/android/JadxProtocol.js +6 -0
  20. package/dist/android/JadxProvider.js +20 -2
  21. package/dist/android/JadxSession.js +23 -4
  22. package/dist/application/AnalysisContextQueries.js +8 -35
  23. package/dist/application/AnalysisDocument.js +32 -0
  24. package/dist/application/AppBundleExecutable.js +67 -21
  25. package/dist/application/CallPathTracing.js +19 -3
  26. package/dist/application/CapabilityInventory.js +27 -3
  27. package/dist/application/ClientConfigurationDocument.js +871 -6
  28. package/dist/application/ClientRegistrationIdentity.js +26 -5
  29. package/dist/application/ClientRegistrationStatus.js +29 -14
  30. package/dist/application/DirectAnalysis.js +97 -33
  31. package/dist/application/Doctor.js +4 -2
  32. package/dist/application/DoctorScope.js +25 -13
  33. package/dist/application/EnhancedLiteralTracing.js +22 -25
  34. package/dist/application/EnhancedTools.js +13 -11
  35. package/dist/application/EvidenceBundleFiles.js +24 -12
  36. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  37. package/dist/application/InventoryProjectionEvidence.js +4 -3
  38. package/dist/application/InvestigationProviders.js +3 -2
  39. package/dist/application/JsonFiles.js +50 -28
  40. package/dist/application/ProcedureAddressResolution.js +11 -0
  41. package/dist/application/ReconstructionCoverageService.js +7 -4
  42. package/dist/application/ReconstructionObligationCandidates.js +5 -1
  43. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  44. package/dist/application/Setup.js +13 -1
  45. package/dist/application/SetupClientConfiguration.js +10 -15
  46. package/dist/application/SetupHost.js +5 -2
  47. package/dist/application/SetupPlan.js +5 -3
  48. package/dist/application/SupportedClients.js +34 -1
  49. package/dist/application/Uninstall.js +4 -3
  50. package/dist/application/Update.js +18 -3
  51. package/dist/application/UpdateRuntime.js +46 -25
  52. package/dist/application/WebModuleTraceService.js +4 -2
  53. package/dist/application/WebNetworkCapturePort.js +1 -0
  54. package/dist/application/WebNetworkCaptureService.js +134 -0
  55. package/dist/application/WebRuntimeService.js +5 -3
  56. package/dist/application/WebScriptExportService.js +2 -2
  57. package/dist/application/WebSourceLocationService.js +4 -2
  58. package/dist/application/WindowsCapabilities.js +1 -1
  59. package/dist/application/WorkflowEvidence.js +82 -0
  60. package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
  61. package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
  62. package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
  63. package/dist/application/binary/BinarySession.js +131 -76
  64. package/dist/application/binary/BinarySessionOpen.js +19 -6
  65. package/dist/application/binary/BinarySessionRecords.js +45 -3
  66. package/dist/application/binary/BinarySessionStatus.js +17 -1
  67. package/dist/application/binary/CompositeProvider.js +13 -0
  68. package/dist/application/binary/LazyAnalysisProvider.js +3 -0
  69. package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
  70. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
  71. package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
  72. package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
  73. package/dist/application/evm/EvmInterfacePort.js +1 -0
  74. package/dist/application/evm/EvmInterfaceService.js +64 -0
  75. package/dist/application/investigation/EvidenceLedger.js +21 -7
  76. package/dist/application/investigation/InvestigationRecords.js +8 -0
  77. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  78. package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
  79. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  80. package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
  81. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  82. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
  83. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
  84. package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
  85. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
  86. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  89. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
  90. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  91. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
  92. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
  93. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
  94. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
  95. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
  96. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
  97. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
  98. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
  99. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
  100. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
  101. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  102. package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
  103. package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
  104. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  105. package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
  106. package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
  107. package/dist/application/workflowInputError.js +18 -0
  108. package/dist/artifacts/ArtifactProvider.js +42 -5
  109. package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
  110. package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
  111. package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
  112. package/dist/artifacts/ZipArtifactReader.js +3 -0
  113. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
  114. package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
  115. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  116. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  117. package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
  118. package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
  119. package/dist/artifacts/apple/NibArchive.js +81 -14
  120. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  121. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  122. package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
  123. package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
  124. package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
  125. package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
  126. package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
  127. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
  128. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
  129. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  130. package/dist/artifacts/readStableArtifact.js +20 -4
  131. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  132. package/dist/browser/CdpCaptureEventHandlers.js +165 -12
  133. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  134. package/dist/browser/CdpCaptureEvents.js +34 -0
  135. package/dist/browser/CdpConnection.js +30 -11
  136. package/dist/browser/CdpOptionalCommand.js +2 -3
  137. package/dist/browser/CdpPageCapture.js +23 -1
  138. package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
  139. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  140. package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
  141. package/dist/browser/WebSourceMapFetcher.js +426 -72
  142. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  143. package/dist/browser/history/CaptureFailures.js +137 -0
  144. package/dist/browser/history/CaptureFormatError.js +10 -0
  145. package/dist/browser/history/CaptureRedaction.js +65 -0
  146. package/dist/browser/history/CaptureRelease.js +17 -0
  147. package/dist/browser/history/HarCapture.js +165 -0
  148. package/dist/browser/history/HarCaptureAdapter.js +20 -0
  149. package/dist/browser/history/HarCaptureProcess.js +57 -0
  150. package/dist/browser/history/HarJson.js +92 -0
  151. package/dist/browser/history/HarSchema.js +72 -0
  152. package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
  153. package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
  154. package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
  155. package/dist/cli/analysisSelector.js +23 -0
  156. package/dist/cli/applicationCommands.js +2 -3
  157. package/dist/cli/artifactCommands.js +26 -1
  158. package/dist/cli/binaryDiagnosticsCommands.js +39 -0
  159. package/dist/cli/coreAnalysisCommands.js +2 -2
  160. package/dist/cli/coreBinaryCommands.js +78 -20
  161. package/dist/cli/electronCommands.js +21 -13
  162. package/dist/cli/evmCommands.js +24 -0
  163. package/dist/cli/firmwareCommands.js +6 -3
  164. package/dist/cli/javascriptApplicationAnalysis.js +20 -3
  165. package/dist/cli/jsonOutput.js +38 -0
  166. package/dist/cli/nativeCallCommands.js +34 -0
  167. package/dist/cli/processCommands.js +1 -1
  168. package/dist/cli/streamedJsonOutput.js +56 -0
  169. package/dist/cli/utilityCommands.js +2 -0
  170. package/dist/cli/webNetworkCaptureCommands.js +40 -0
  171. package/dist/cli/webRuntimeCommands.js +8 -8
  172. package/dist/cli.js +11 -4
  173. package/dist/cliBrowserScenarioCommands.js +2 -2
  174. package/dist/cliCommandNames.js +6 -1
  175. package/dist/cliJsonInput.js +35 -1
  176. package/dist/cliOutput.js +21 -6
  177. package/dist/composition/binaryDiagnostics.js +8 -0
  178. package/dist/composition/evm.js +4 -0
  179. package/dist/composition/webNetworkCaptures.js +6 -0
  180. package/dist/config/environment.js +4 -0
  181. package/dist/config/ghidraStartupTimeout.js +17 -0
  182. package/dist/config/mcpResponseBudget.js +22 -0
  183. package/dist/config/parseConfig.js +2 -1
  184. package/dist/contracts/artifactToolContracts.js +6 -0
  185. package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
  186. package/dist/contracts/browserToolContracts.js +4 -3
  187. package/dist/contracts/enhancedInputs.js +5 -3
  188. package/dist/contracts/enhancedToolContracts.js +3 -3
  189. package/dist/contracts/errorSchemas.js +8 -1
  190. package/dist/contracts/evm/evmToolContracts.js +20 -0
  191. package/dist/contracts/hopperMemoryContracts.js +2 -5
  192. package/dist/contracts/investigationExamples.js +2 -2
  193. package/dist/contracts/javascript/electronToolContracts.js +1 -1
  194. package/dist/contracts/managed/managedToolContracts.js +8 -6
  195. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
  196. package/dist/contracts/native/nativeToolContracts.js +21 -3
  197. package/dist/contracts/officialToolContracts.js +26 -24
  198. package/dist/contracts/process/processCaptureExample.js +2 -0
  199. package/dist/contracts/promptContracts.js +3 -3
  200. package/dist/contracts/sessionLifecycleInputs.js +18 -5
  201. package/dist/contracts/sessionStatusContract.js +8 -2
  202. package/dist/contracts/sessionToolContracts.js +8 -3
  203. package/dist/contracts/sessionToolSchemas.js +8 -4
  204. package/dist/contracts/toolContractExamples.js +1 -2
  205. package/dist/contracts/toolContractHelpers.js +4 -1
  206. package/dist/contracts/toolContracts.js +6 -0
  207. package/dist/contracts/toolEffects.js +30 -1
  208. package/dist/contracts/toolOutputSchemaGroups.js +33 -28
  209. package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
  210. package/dist/contracts/toolSchemaMetadata.js +69 -10
  211. package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
  212. package/dist/domain/analysisErrorBase.js +22 -2
  213. package/dist/domain/analysisErrorCore.js +61 -5
  214. package/dist/domain/analysisErrorPresentation.js +95 -12
  215. package/dist/domain/analysisErrorProjection.js +148 -19
  216. package/dist/domain/analysisSnapshot.js +166 -2
  217. package/dist/domain/android/androidAnalysis.js +2 -4
  218. package/dist/domain/android/androidApplication.js +17 -9
  219. package/dist/domain/apple/appleApplication.js +41 -14
  220. package/dist/domain/apple/dyldEnvironment.js +73 -0
  221. package/dist/domain/apple/dyldPaths.js +81 -0
  222. package/dist/domain/apple/dylibResolution.js +478 -0
  223. package/dist/domain/apple/dylibResolutionFindings.js +77 -0
  224. package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
  225. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  226. package/dist/domain/apple/keyedArchive.js +9 -1
  227. package/dist/domain/apple/machoContainer.js +54 -0
  228. package/dist/domain/apple/plistNumbers.js +76 -0
  229. package/dist/domain/artifactIdentity.js +29 -0
  230. package/dist/domain/artifactInventoryEvidence.js +19 -24
  231. package/dist/domain/artifactPathSyntax.js +1 -1
  232. package/dist/domain/bridgeCandidateProjection.js +71 -0
  233. package/dist/domain/browserCompleteness.js +1 -0
  234. package/dist/domain/browserObservation.js +1 -1
  235. package/dist/domain/browserObservationError.js +24 -5
  236. package/dist/domain/browserObservationSchemas.js +13 -0
  237. package/dist/domain/browserScenarioValues.js +5 -2
  238. package/dist/domain/bundleComparison.js +3 -2
  239. package/dist/domain/callPathSchemas.js +1 -1
  240. package/dist/domain/canonicalDigest.js +13 -1
  241. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  242. package/dist/domain/canonicalOrdering.js +9 -5
  243. package/dist/domain/changedBehavior.js +9 -9
  244. package/dist/domain/comparisonSourceEvidence.js +40 -0
  245. package/dist/domain/comparisonStatus.js +2 -30
  246. package/dist/domain/configurationErrors.js +1 -1
  247. package/dist/domain/conformanceTrustGate.js +0 -16
  248. package/dist/domain/evidence.js +78 -11
  249. package/dist/domain/evidenceBundle.js +42 -1
  250. package/dist/domain/evidenceErrors.js +12 -1
  251. package/dist/domain/evm/evmInterface.js +63 -0
  252. package/dist/domain/explicitSensitiveFailure.js +108 -0
  253. package/dist/domain/explicitSensitiveValues.js +10 -0
  254. package/dist/domain/firmware/firmwareAnalysis.js +10 -4
  255. package/dist/domain/hopperErrors.js +23 -2
  256. package/dist/domain/hopperValues.js +51 -8
  257. package/dist/domain/immutableJson.js +114 -0
  258. package/dist/domain/inputIssueProjection.js +3 -0
  259. package/dist/domain/javascript/electronActiveObservation.js +37 -6
  260. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  261. package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
  262. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  263. package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
  264. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  265. package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
  266. package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
  267. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  268. package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
  269. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  270. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  271. package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
  272. package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
  273. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  274. package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
  275. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  276. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  277. package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
  278. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  279. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  280. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  281. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
  282. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  283. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
  284. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  285. package/dist/domain/jsonSerialization.js +109 -0
  286. package/dist/domain/jsonValue.js +91 -3
  287. package/dist/domain/localPath.js +8 -0
  288. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  289. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  290. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  291. package/dist/domain/managed/managedNativeVerification.js +3 -9
  292. package/dist/domain/native/binaryLayout.js +357 -0
  293. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  294. package/dist/domain/native/nativeCallObservation.js +186 -0
  295. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  296. package/dist/domain/native/objcSwiftMetadata.js +0 -39
  297. package/dist/domain/native/recordedCrash.js +266 -0
  298. package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
  299. package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
  300. package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
  301. package/dist/domain/process/processCaptureParsing.js +54 -0
  302. package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
  303. package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
  304. package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
  305. package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
  306. package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
  307. package/dist/domain/propertyListKeys.js +1 -1
  308. package/dist/domain/propertyListXmlText.js +19 -0
  309. package/dist/domain/providerAdapterError.js +1 -1
  310. package/dist/domain/providerOperationHealth.js +54 -0
  311. package/dist/domain/providerSelectionError.js +4 -2
  312. package/dist/domain/reconstructionVerification.js +9 -46
  313. package/dist/domain/reconstructionVerificationSchemas.js +3 -3
  314. package/dist/domain/residualUnknown.js +3 -2
  315. package/dist/domain/staticRuntimeCorrelation.js +9 -46
  316. package/dist/domain/webBundleAnalysis.js +20 -8
  317. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  318. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  319. package/dist/domain/webCaptureDiff.js +1 -0
  320. package/dist/domain/webNetworkCapture.js +118 -0
  321. package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
  322. package/dist/domain/webRuntime.js +19 -5
  323. package/dist/domain/webSourceLocation.js +1 -0
  324. package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
  325. package/dist/dotnet/ManagedMemberInspector.js +4 -2
  326. package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
  327. package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
  328. package/dist/dotnet/ManagedMemberRows.js +14 -3
  329. package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
  330. package/dist/dotnet/ManagedMetadataInventory.js +38 -28
  331. package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
  332. package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
  333. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
  334. package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
  335. package/dist/dotnet/ManagedPeReader.js +11 -0
  336. package/dist/evm/EvmBytecodeCarrier.js +21 -0
  337. package/dist/evm/EvmWorkerLimits.js +40 -0
  338. package/dist/evm/EvmoleFailures.js +126 -0
  339. package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
  340. package/dist/evm/EvmoleInterfaceProvider.js +273 -0
  341. package/dist/evm/EvmoleInterfaceWorker.js +87 -0
  342. package/dist/evm/EvmoleRelease.js +16 -0
  343. package/dist/firmware/FirmwareCommand.js +1 -0
  344. package/dist/firmware/FirmwareFiles.js +1 -1
  345. package/dist/generatedPackageMetadata.js +2 -2
  346. package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
  347. package/dist/ghidra/GhidraClient.js +47 -14
  348. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  349. package/dist/ghidra/GhidraFunctionValues.js +10 -7
  350. package/dist/ghidra/GhidraInstallation.js +18 -21
  351. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  352. package/dist/ghidra/GhidraJavaLaunch.js +62 -0
  353. package/dist/ghidra/GhidraLauncher.js +34 -16
  354. package/dist/ghidra/GhidraProvider.js +2 -2
  355. package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
  356. package/dist/ghidra/GhidraProviderClient.js +23 -12
  357. package/dist/ghidra/GhidraSessionError.js +11 -7
  358. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  359. package/dist/ghidra/GhidraTransport.js +20 -0
  360. package/dist/hopper/BridgeLauncher.js +33 -11
  361. package/dist/hopper/HopperAnalysisProfile.js +62 -4
  362. package/dist/hopper/HopperCleanup.js +15 -3
  363. package/dist/hopper/HopperClient.js +222 -14
  364. package/dist/hopper/HopperFileOffset.js +237 -0
  365. package/dist/hopper/HopperMachOImage.js +196 -0
  366. package/dist/hopper/HopperOperationStage.js +6 -0
  367. package/dist/hopper/HopperProvider.js +63 -9
  368. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  369. package/dist/hopper/HopperRegexSearch.js +137 -0
  370. package/dist/hopper/HopperRegexWorker.js +27 -0
  371. package/dist/hopper/HopperRequestQueue.js +68 -19
  372. package/dist/hopper/HopperTargetLease.js +3 -2
  373. package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
  374. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  375. package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
  376. package/dist/inspector/V8InspectorProvider.js +47 -11
  377. package/dist/javascript/recovery/WakaruCommand.js +3 -0
  378. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  379. package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
  380. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  381. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  382. package/dist/mcpDoctor.js +62 -2
  383. package/dist/native/AppleDispatchCoverage.js +47 -6
  384. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  385. package/dist/native/AppleDispatchMetadata.js +6 -3
  386. package/dist/native/AppleMachoFixups.js +48 -24
  387. package/dist/native/AppleMachoSelection.js +32 -16
  388. package/dist/native/AppleObjcCategories.js +6 -2
  389. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  390. package/dist/native/AppleObjcProperties.js +2 -1
  391. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  392. package/dist/native/AppleSwiftVtables.js +21 -15
  393. package/dist/native/CommandRunner.js +82 -84
  394. package/dist/native/LldbCallTracer.js +541 -0
  395. package/dist/native/LldbRetainedObservations.js +178 -0
  396. package/dist/native/NativeCallObservation.js +194 -0
  397. package/dist/native/NativeMacOSProvider.js +117 -20
  398. package/dist/native/NativeMacOSProviderMetadata.js +8 -3
  399. package/dist/native/SignatureTargetBinding.js +155 -0
  400. package/dist/native/parsers/lipo.js +71 -1
  401. package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
  402. package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
  403. package/dist/native/pwntools/PwntoolsFailures.js +180 -0
  404. package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
  405. package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
  406. package/dist/native/pwntools/PwntoolsRelease.js +19 -0
  407. package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
  408. package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
  409. package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
  410. package/dist/process/DarwinProcessRunTokenReader.js +293 -0
  411. package/dist/process/ExecFileOutput.js +20 -0
  412. package/dist/process/OwnedCommand.js +118 -0
  413. package/dist/process/ProcessOwnership.js +431 -51
  414. package/dist/process/ProcessOwnershipObservation.js +209 -27
  415. package/dist/process/ProviderProcess.js +68 -10
  416. package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
  417. package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
  418. package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
  419. package/dist/{application → process/capture}/ProcessHarness.js +195 -29
  420. package/dist/{application → process/capture}/ProcessSampling.js +2 -2
  421. package/dist/server/EvidenceMcpServer.js +146 -0
  422. package/dist/server/createServer.js +37 -8
  423. package/dist/server/promptCompletion.js +10 -3
  424. package/dist/server/registerAndroidTools.js +2 -4
  425. package/dist/server/registerApplicationTools/helpers.js +2 -4
  426. package/dist/server/registerArtifactComparisonTool.js +11 -7
  427. package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
  428. package/dist/server/registerBrowserScenarioTool.js +2 -4
  429. package/dist/server/registerBrowserTools.js +2 -4
  430. package/dist/server/registerBundleComparisonTool.js +2 -3
  431. package/dist/server/registerCloseLifecycleTool.js +8 -18
  432. package/dist/server/registerElectronTools.js +2 -4
  433. package/dist/server/registerEnhancedTools.js +18 -59
  434. package/dist/server/registerEvidenceTools.js +3 -5
  435. package/dist/server/registerEvmTools.js +15 -0
  436. package/dist/server/registerFirmwareTools.js +2 -4
  437. package/dist/server/registerFunctionComparisonTool.js +10 -6
  438. package/dist/server/registerInvestigationTools.js +7 -7
  439. package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
  440. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
  441. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
  442. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
  443. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
  444. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
  445. package/dist/server/registerOfficialTools.js +2 -4
  446. package/dist/server/registerProcessComparisonTool.js +72 -46
  447. package/dist/server/registerRecordedCrashTools.js +15 -0
  448. package/dist/server/registerSessionRecordTools.js +5 -6
  449. package/dist/server/registerSessionStatusTool.js +17 -3
  450. package/dist/server/registerSessionTools.js +13 -5
  451. package/dist/server/registerWebModuleTool.js +2 -4
  452. package/dist/server/registerWebNetworkCaptureTool.js +26 -0
  453. package/dist/server/registerWebRuntimeTools.js +3 -7
  454. package/dist/server/registerWebScriptTool.js +2 -4
  455. package/dist/server/registerWebSourceLocationTool.js +2 -4
  456. package/dist/server/runDerivedOperation.js +15 -3
  457. package/dist/server/sessionAvailabilityPolicy.js +3 -1
  458. package/dist/server/sessionToolPolicies.js +1 -1
  459. package/dist/server/toolRegistrationOptions.js +2 -2
  460. package/dist/server/toolResult.js +63 -11
  461. package/dist/server/toolResultEncoding.js +33 -0
  462. package/install.sh +1 -1
  463. package/native/windows/build/manifest.json +2 -2
  464. package/native/windows/build/rea-windows-x64.node +0 -0
  465. package/package.json +42 -9
  466. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  467. package/scripts/electron-active-hook.cjs +241 -37
  468. package/scripts/rea.mjs +11 -3
  469. package/skills/reverse-engineer-anything/SKILL.md +32 -4
  470. package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
  471. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
  472. package/third_party/README.md +60 -0
  473. package/third_party/evmole/LICENSE +21 -0
  474. package/third_party/evmole/README.md +22 -0
  475. package/third_party/pwndbg/LICENSE.md +21 -0
  476. package/third_party/pwndbg/README.md +23 -0
  477. package/third_party/pwntools/README.md +40 -0
  478. package/dist/application/AuthorizedArtifactInventory.js +0 -7
  479. package/dist/application/ProcessCaptureLifecycle.js +0 -299
  480. package/dist/application/StoreFileLock.js +0 -124
  481. package/dist/contracts/processCaptureExample.js +0 -2
  482. package/dist/domain/bytecodeProvider.js +0 -178
  483. package/dist/domain/customProtocolCapture.js +0 -137
  484. package/dist/domain/eventProcessTree.js +0 -225
  485. package/dist/domain/mobileApplicationInvestigation.js +0 -159
  486. package/dist/domain/packageAnalysis.js +0 -123
  487. package/dist/domain/peInspection.js +0 -197
  488. package/dist/domain/processCaptureParsing.js +0 -21
  489. package/dist/domain/protocolCapture.js +0 -217
  490. package/dist/domain/runtimeIdentification.js +0 -212
  491. package/dist/generatedMcpToolCatalog.js +0 -37
  492. package/dist/ghidra/GhidraDefaults.js +0 -2
  493. /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
  494. /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
  495. /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
  496. /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
  497. /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
  498. /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
  499. /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
  500. /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
  501. /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
  502. /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
  503. /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
  504. /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
  505. /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
  506. /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
  507. /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
@@ -4,36 +4,72 @@ 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
8
  import { buildInterfaceBuilderAnalysis, interfaceBuilderLimitsSchema, } from "../../domain/apple/interfaceBuilderGraph.js";
8
9
  import { mergeNibHierarchies, projectNibViewHierarchy, } from "./NibViewHierarchy.js";
9
10
  import { jsonValueSchema } from "../../domain/jsonValue.js";
10
- const MAX_DOCUMENT_BYTES = 64 * 1024 * 1024;
11
+ import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
12
+ const MAX_AGGREGATE_INPUT_BYTES = 32 * 1024 * 1024;
13
+ const MAX_AGGREGATE_DECODE_BYTES = 256 * 1024 * 1024;
14
+ const MAX_REPORTED_OMITTED_ARCHIVES = 64;
11
15
  /** Decode compiled Interface Builder archives from a local app bundle. */
12
16
  export const analyzeInterfaceBuilderBundle = async (input) => {
13
17
  const limits = interfaceBuilderLimitsSchema.parse(input.limits ?? {});
14
18
  const reader = new DirectoryArtifactReader(input.bundlePath);
15
19
  const documents = [];
16
20
  const invalid = [];
21
+ const omittedArchives = [];
22
+ let unreportedOmittedArchives = 0;
17
23
  const incompleteHierarchies = new Map();
18
24
  const prototypeKeyOmissions = new Map();
19
25
  let omitted = 0;
20
26
  let attempted = 0;
27
+ let candidates = 0;
28
+ let aggregateInputBytes = 0;
29
+ const decodeBudget = new InterfaceBuilderDecodeBudget(MAX_AGGREGATE_DECODE_BYTES);
30
+ const recordOmittedArchive = (path, reason) => {
31
+ if (omittedArchives.length < MAX_REPORTED_OMITTED_ARCHIVES)
32
+ omittedArchives.push({ path, reason });
33
+ else
34
+ unreportedOmittedArchives += 1;
35
+ };
21
36
  try {
22
37
  for await (const entry of reader.entries(input.signal)) {
23
38
  if (entry.kind !== "file" || !isInterfaceBuilderArchive(entry.path))
24
39
  continue;
25
- if (attempted >= limits.max_documents) {
40
+ candidates += 1;
41
+ if (candidates > limits.max_documents) {
26
42
  omitted += 1;
43
+ recordOmittedArchive(entry.path, "max_documents");
27
44
  continue;
28
45
  }
29
- attempted += 1;
30
46
  try {
31
- const bytes = await readEntry(reader, entry, input.signal);
32
- const nib = bytes.subarray(0, 10).toString("ascii") === "NIBArchive"
33
- ? projectNibArchive(decodeNibArchive(bytes))
34
- : null;
47
+ const remainingInputBytes = MAX_AGGREGATE_INPUT_BYTES - aggregateInputBytes;
48
+ if (entry.declaredSize !== null &&
49
+ entry.declaredSize > remainingInputBytes) {
50
+ omitted += 1;
51
+ recordOmittedArchive(entry.path, "aggregate_decode_budget_exhausted");
52
+ continue;
53
+ }
54
+ attempted += 1;
55
+ const bytes = await readEntry(reader, entry, input.signal, remainingInputBytes);
56
+ aggregateInputBytes += bytes.length;
57
+ const isNibArchive = bytes.subarray(0, 10).toString("ascii") === "NIBArchive";
58
+ let nib = null;
59
+ let xmlText;
60
+ if (isNibArchive) {
61
+ const documentBudget = new InterfaceBuilderDecodeBudget(decodeBudget.remainingBytes);
62
+ nib = projectNibArchive(decodeNibArchive(bytes, documentBudget), documentBudget, limits.max_objects);
63
+ decodeBudget.reserve(documentBudget.usedBytes, "NIBArchive representation exceeds the aggregate Interface Builder decode budget");
64
+ }
65
+ else {
66
+ if (bytes.subarray(0, 8).toString("ascii") !== "bplist00")
67
+ xmlText = decodeXmlPlistText(bytes);
68
+ const decodedReservation = estimatePropertyListDecodeBytes(bytes, decodeBudget.remainingBytes, xmlText);
69
+ decodeBudget.reserve(decodedReservation, "plist representation exceeds the aggregate Interface Builder decode budget");
70
+ }
35
71
  const { value: raw, omittedPrototypeKeys } = nib === null
36
- ? decodePlist(bytes)
72
+ ? decodePlist(bytes, xmlText)
37
73
  : { value: nib.raw, omittedPrototypeKeys: 0 };
38
74
  if (nib !== null && nib.omitted > 0)
39
75
  incompleteHierarchies.set(entry.path, nib.omitted);
@@ -52,6 +88,11 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
52
88
  catch (cause) {
53
89
  if (input.signal?.aborted === true)
54
90
  throw cause;
91
+ if (cause instanceof InterfaceBuilderDecodeBudgetExceeded) {
92
+ omitted += 1;
93
+ recordOmittedArchive(entry.path, cause.reason);
94
+ continue;
95
+ }
55
96
  invalid.push(`${entry.path}: ${cause instanceof Error ? cause.message : "archive decode failed"}`);
56
97
  }
57
98
  }
@@ -69,13 +110,17 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
69
110
  incompleteHierarchies,
70
111
  prototypeKeyOmissions,
71
112
  invalid,
113
+ omittedArchives,
114
+ unreportedOmittedArchives,
72
115
  attempted,
73
116
  omitted,
74
117
  });
75
118
  };
76
119
  const finalizeHierarchyCoverage = (result, counts) => {
77
- const { incompleteHierarchies, prototypeKeyOmissions, invalid } = counts;
78
- const archiveDecodePartial = invalid.length > 0 || prototypeKeyOmissions.size > 0;
120
+ const { incompleteHierarchies, prototypeKeyOmissions, invalid, omittedArchives, unreportedOmittedArchives, } = counts;
121
+ const archiveDecodePartial = invalid.length > 0 ||
122
+ prototypeKeyOmissions.size > 0 ||
123
+ omittedArchives.length > 0;
79
124
  return {
80
125
  ...result,
81
126
  documents: result.documents.map((document) => ({
@@ -102,11 +147,17 @@ const finalizeHierarchyCoverage = (result, counts) => {
102
147
  status: archiveDecodePartial
103
148
  ? "partial"
104
149
  : "complete",
105
- reason: invalid.length > 0
106
- ? "one_or_more_archives_invalid"
107
- : prototypeKeyOmissions.size > 0
108
- ? "dictionary_entries_omitted"
109
- : null,
150
+ reason: omittedArchives.some(({ reason }) => reason === "aggregate_decode_budget_exhausted")
151
+ ? "aggregate_decode_budget_exhausted"
152
+ : omittedArchives.some(({ reason }) => reason === "max_documents")
153
+ ? "document_limit_reached"
154
+ : omittedArchives.length > 0
155
+ ? "archive_decode_budget_exhausted"
156
+ : invalid.length > 0
157
+ ? "one_or_more_archives_invalid"
158
+ : prototypeKeyOmissions.size > 0
159
+ ? "dictionary_entries_omitted"
160
+ : null,
110
161
  examined: counts.attempted,
111
162
  omitted: counts.omitted,
112
163
  },
@@ -130,27 +181,70 @@ const finalizeHierarchyCoverage = (result, counts) => {
130
181
  `Some Interface Builder archives could not be decoded: ${invalid.slice(0, 16).join("; ")}`,
131
182
  ]),
132
183
  ...[...prototypeKeyOmissions].map(([path, count]) => `${path}: ${omittedPrototypeKeysLimitation(count)}`),
184
+ ...omittedArchives.map(({ path, reason }) => `${path}: omitted because ${reason.replaceAll("_", " ")}.`),
185
+ ...(unreportedOmittedArchives === 0
186
+ ? []
187
+ : [
188
+ `${unreportedOmittedArchives} additional omitted archive path(s) and their reasons were not retained; reporting is bounded to ${MAX_REPORTED_OMITTED_ARCHIVES} paths.`,
189
+ ]),
133
190
  ],
134
191
  };
135
192
  };
136
193
  /** Project decoded NIB records into the same bounded graph input as ibtool. */
137
- const projectNibArchive = (archive) => {
194
+ const projectNibArchive = (archive, budget, maxHierarchyNodes) => {
138
195
  const byId = new Map(archive.objects.map((object) => [object.id, object]));
196
+ const normalizedClassNames = new Map();
197
+ const normalizeClassName = (value) => {
198
+ const known = normalizedClassNames.get(value);
199
+ if (known !== undefined)
200
+ return known;
201
+ const normalized = value.replace(/\0+$/u, "");
202
+ normalizedClassNames.set(value, normalized);
203
+ return normalized;
204
+ };
205
+ const decodedStrings = new Map();
206
+ const decodedString = (objectId, object) => {
207
+ if (decodedStrings.has(objectId))
208
+ return decodedStrings.get(objectId) ?? null;
209
+ const data = object.values["NS.bytes"];
210
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
211
+ decodedStrings.set(objectId, null);
212
+ return null;
213
+ }
214
+ const encoded = data.$nib_data_base64;
215
+ if (typeof encoded !== "string") {
216
+ decodedStrings.set(objectId, null);
217
+ return null;
218
+ }
219
+ budget.reserve(64 + encoded.length * 2, "NIBArchive string projection exceeds the aggregate Interface Builder decode budget");
220
+ const value = Buffer.from(encoded, "base64").toString("utf8");
221
+ decodedStrings.set(objectId, value);
222
+ return value;
223
+ };
224
+ let projectedFields = 0;
225
+ for (const object of archive.objects)
226
+ projectedFields += Object.keys(object.values).length;
227
+ budget.reserve(archive.objects.length * 128 + projectedFields * 128, "NIBArchive graph projection exceeds the aggregate Interface Builder decode budget");
228
+ budget.reserve(archive.classes.length * 96, "NIBArchive class projection exceeds the aggregate Interface Builder decode budget");
139
229
  const dereference = (value) => {
140
230
  if (typeof value !== "object" || value === null || Array.isArray(value))
141
231
  return value;
232
+ const encodedData = value.$nib_data_base64;
233
+ if (typeof encodedData === "string") {
234
+ budget.reserveBase64JsonStringOccurrence(encodedData);
235
+ return value;
236
+ }
142
237
  const ref = value.$nib_object_ref;
143
238
  if (typeof ref !== "number")
144
239
  return value;
145
240
  const target = byId.get(ref);
146
241
  if (target === undefined)
147
242
  return undefined;
148
- if (target.class_name.replace(/\0+$/u, "") === "NSString") {
149
- const data = target.values["NS.bytes"];
150
- if (typeof data === "object" && data !== null && !Array.isArray(data)) {
151
- const encoded = data.$nib_data_base64;
152
- if (typeof encoded === "string")
153
- return Buffer.from(encoded, "base64").toString("utf8");
243
+ if (normalizeClassName(target.class_name) === "NSString") {
244
+ const string = decodedString(ref, target);
245
+ if (string !== null) {
246
+ budget.reserveJsonStringOccurrence(string);
247
+ return string;
154
248
  }
155
249
  }
156
250
  return { objectID: String(ref) };
@@ -162,26 +256,30 @@ const projectNibArchive = (archive) => {
162
256
  if (typeof ref !== "number")
163
257
  return null;
164
258
  const target = byId.get(ref);
165
- const data = target?.values["NS.bytes"];
166
- if (target?.class_name.replace(/\0+$/u, "") !== "NSString")
259
+ if (target === undefined ||
260
+ normalizeClassName(target.class_name) !== "NSString")
167
261
  return null;
168
- if (typeof data !== "object" || data === null || Array.isArray(data))
262
+ const string = decodedString(ref, target);
263
+ if (string === null)
169
264
  return null;
170
- const encoded = data.$nib_data_base64;
171
- return typeof encoded === "string"
172
- ? Buffer.from(encoded, "base64").toString("utf8")
173
- : null;
265
+ budget.reserveJsonStringOccurrence(string);
266
+ return string;
174
267
  };
268
+ const runtimeClasses = new Map();
175
269
  const runtimeClass = (objectId) => {
270
+ if (runtimeClasses.has(objectId))
271
+ return runtimeClasses.get(objectId) ?? null;
176
272
  const object = byId.get(objectId);
177
273
  if (object === undefined)
178
274
  return null;
179
- const storedClass = object.class_name.replace(/\0+$/u, "");
180
- if (storedClass === "NSClassSwapper")
181
- return referencedString(object.values.NSClassName) ?? storedClass;
182
- return storedClass === "UIClassSwapper"
183
- ? (referencedString(object.values.UIClassName) ?? storedClass)
184
- : storedClass;
275
+ const storedClass = normalizeClassName(object.class_name);
276
+ const resolvedClass = storedClass === "NSClassSwapper"
277
+ ? (referencedString(object.values.NSClassName) ?? storedClass)
278
+ : storedClass === "UIClassSwapper"
279
+ ? (referencedString(object.values.UIClassName) ?? storedClass)
280
+ : storedClass;
281
+ runtimeClasses.set(objectId, resolvedClass);
282
+ return resolvedClass;
185
283
  };
186
284
  const objects = Object.fromEntries(archive.objects
187
285
  .filter((object) => {
@@ -189,22 +287,29 @@ const projectNibArchive = (archive) => {
189
287
  return !/^(?:NSObject|NSIBObjectData|NSString|NSMutableString|NSNumber|NSArray|NSMutableArray|NSSet|NSMutableSet|NSDictionary|NSMutableDictionary|NSApplication|NSNib.*Connector|UIRuntime\w*Connection)$/u.test(name);
190
288
  })
191
289
  .map((object) => {
192
- const className = runtimeClass(object.id) ?? object.class_name.replace(/\0+$/u, "");
193
- const strings = Object.entries(object.values).flatMap(([key, value]) => {
290
+ const className = runtimeClass(object.id) ?? normalizeClassName(object.class_name);
291
+ budget.reserveJsonStringOccurrence(className);
292
+ let name = className;
293
+ for (const [key, value] of Object.entries(object.values)) {
294
+ if (!/(?:title|label|identifier|accessibility|name|contents)/iu.test(key))
295
+ continue;
194
296
  const resolved = dereference(value);
195
- return typeof resolved === "string" ? [[key, resolved]] : [];
196
- });
197
- const name = strings.find(([key]) => /(?:title|label|identifier|accessibility|name|contents)/iu.test(key ?? ""))?.[1] ?? className;
297
+ if (typeof resolved !== "string")
298
+ continue;
299
+ name = resolved;
300
+ break;
301
+ }
302
+ budget.reserveJsonStringOccurrence(name);
198
303
  return [
199
304
  String(object.id),
200
305
  {
201
306
  customClass: className,
202
307
  label: name,
203
308
  objectID: String(object.id),
204
- nibValues: Object.fromEntries(Object.entries(object.values).map(([key, value]) => [
205
- key,
206
- dereference(value) ?? null,
207
- ])),
309
+ nibValues: Object.fromEntries(Object.entries(object.values).map(([key, value]) => {
310
+ budget.reserveJsonPropertyNameOccurrence(key);
311
+ return [key, dereference(value) ?? null];
312
+ })),
208
313
  },
209
314
  ];
210
315
  }));
@@ -218,7 +323,7 @@ const projectNibArchive = (archive) => {
218
323
  : null;
219
324
  };
220
325
  for (const object of archive.objects) {
221
- const className = object.class_name.replace(/\0+$/u, "");
326
+ const className = normalizeClassName(object.class_name);
222
327
  // AppKit connectors use NS-prefixed keys; UIKit's runtime outlet and
223
328
  // event connections use UI-prefixed keys with the same roles.
224
329
  const uiKit = /^UIRuntime\w*Connection$/u.test(className);
@@ -235,6 +340,7 @@ const projectNibArchive = (archive) => {
235
340
  : className.includes("Control") || className.includes("Event")
236
341
  ? "action"
237
342
  : className;
343
+ budget.reserveJsonStringOccurrence(type);
238
344
  const eventMask = values.UIEventMask;
239
345
  // The source is the outlet owner or the sending control; the destination
240
346
  // is the outlet value or the action target, and a nil target is the
@@ -249,16 +355,26 @@ const projectNibArchive = (archive) => {
249
355
  });
250
356
  }
251
357
  let hierarchyOmitted = 0;
358
+ let hierarchyNodeCount = 0;
252
359
  const hierarchyFor = (objectId, seen, depth) => {
253
360
  if (depth > 32 || seen.has(objectId)) {
254
361
  hierarchyOmitted += 1;
255
362
  return null;
256
363
  }
364
+ if (hierarchyNodeCount >= maxHierarchyNodes) {
365
+ hierarchyOmitted += 1;
366
+ return null;
367
+ }
368
+ if (!budget.tryReserve(128)) {
369
+ hierarchyOmitted += 1;
370
+ return null;
371
+ }
257
372
  const object = byId.get(objectId);
258
373
  if (object === undefined) {
259
374
  hierarchyOmitted += 1;
260
375
  return null;
261
376
  }
377
+ hierarchyNodeCount += 1;
262
378
  const nextSeen = new Set(seen).add(objectId);
263
379
  const children = [];
264
380
  for (const [key, value] of Object.entries(object.values)) {
@@ -288,7 +404,7 @@ const projectNibArchive = (archive) => {
288
404
  }
289
405
  return { objectID: String(objectId), children };
290
406
  };
291
- const ibData = archive.objects.find(({ class_name }) => class_name.replace(/\0+$/u, "") === "NSIBObjectData");
407
+ const ibData = archive.objects.find(({ class_name }) => normalizeClassName(class_name) === "NSIBObjectData");
292
408
  const rootId = reference(ibData?.values.NSRoot);
293
409
  const hierarchyRoots = rootId === null ? [] : [rootId];
294
410
  for (const hierarchyRoot of hierarchyRoots) {
@@ -296,15 +412,19 @@ const projectNibArchive = (archive) => {
296
412
  if (root !== null)
297
413
  hierarchy.push(root);
298
414
  }
299
- const viewHierarchy = projectNibViewHierarchy(archive.objects, new Set(Object.keys(objects).map(Number)));
300
- const merged = mergeNibHierarchies(hierarchy, viewHierarchy.hierarchy ?? []);
415
+ const viewHierarchy = projectNibViewHierarchy(archive.objects, new Set(Object.keys(objects).map(Number)), () => budget.tryReserve(128), maxHierarchyNodes);
416
+ const merged = mergeNibHierarchies(hierarchy, viewHierarchy.hierarchy ?? [], () => budget.tryReserve(96), maxHierarchyNodes);
301
417
  return {
302
418
  omitted: viewHierarchy.omitted + hierarchyOmitted + merged.omitted,
303
419
  raw: jsonValueSchema.parse({
304
420
  "com.apple.ibtool.document.objects": objects,
305
421
  "com.apple.ibtool.document.connections": connections,
306
422
  "com.apple.ibtool.document.hierarchy": merged.hierarchy,
307
- "com.apple.ibtool.document.classes": Object.fromEntries(archive.classes.map((name) => [name.replace(/\0+$/u, ""), {}])),
423
+ "com.apple.ibtool.document.classes": Object.fromEntries(archive.classes.map((name) => {
424
+ const className = normalizeClassName(name);
425
+ budget.reserveJsonPropertyNameOccurrence(className);
426
+ return [className, {}];
427
+ })),
308
428
  }),
309
429
  };
310
430
  };
@@ -312,9 +432,9 @@ const isInterfaceBuilderArchive = (path) => {
312
432
  const lower = path.toLowerCase();
313
433
  return lower.endsWith(".nib") || lower.endsWith("/objects.nib");
314
434
  };
315
- const readEntry = async (reader, entry, signal) => {
316
- if (entry.declaredSize !== null && entry.declaredSize > MAX_DOCUMENT_BYTES)
317
- throw new RangeError("archive exceeds the 64 MiB per-document decode limit");
435
+ const readEntry = async (reader, entry, signal, maxInputBytes = MAX_AGGREGATE_INPUT_BYTES) => {
436
+ if (entry.declaredSize !== null && entry.declaredSize > maxInputBytes)
437
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "archive exceeds the aggregate Interface Builder decode budget");
318
438
  const stream = await reader.open(entry, signal);
319
439
  const chunks = [];
320
440
  let length = 0;
@@ -323,18 +443,18 @@ const readEntry = async (reader, entry, signal) => {
323
443
  ? chunk
324
444
  : Buffer.from(chunk);
325
445
  length += bytes.length;
326
- if (length > MAX_DOCUMENT_BYTES) {
446
+ if (length > maxInputBytes) {
327
447
  stream.destroy();
328
- throw new RangeError("archive exceeded the 64 MiB per-document decode limit");
448
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "archive exceeded the aggregate Interface Builder decode budget");
329
449
  }
330
450
  chunks.push(bytes);
331
451
  }
332
452
  return Buffer.concat(chunks, length);
333
453
  };
334
454
  /** Project decoded plist data and dates while retaining omitted-key coverage. */
335
- const decodePlist = (bytes) => {
455
+ const decodePlist = (bytes, xmlText) => {
336
456
  const { value, omittedPrototypeKeys } = bytes.subarray(0, 8).toString("ascii") === "bplist00"
337
457
  ? { value: parseBinary(bytes), omittedPrototypeKeys: 0 }
338
- : parseXmlPropertyList(bytes.toString("utf8"));
458
+ : parseXmlPropertyList(xmlText ?? decodeXmlPlistText(bytes));
339
459
  return { value: projectPlistValue(value).value, omittedPrototypeKeys };
340
460
  };
@@ -0,0 +1,195 @@
1
+ import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
2
+ /** A named resource-limit failure that keeps budget exhaustion out of decode errors. */
3
+ export class InterfaceBuilderDecodeBudgetExceeded extends Error {
4
+ reason;
5
+ constructor(reason, message) {
6
+ super(message);
7
+ this.reason = reason;
8
+ this.name = "InterfaceBuilderDecodeBudgetExceeded";
9
+ }
10
+ }
11
+ /** Shared byte budget for decoder records and projected archive data. */
12
+ export class InterfaceBuilderDecodeBudget {
13
+ #initialBytes;
14
+ #remainingBytes;
15
+ constructor(maxBytes) {
16
+ this.#initialBytes = maxBytes;
17
+ this.#remainingBytes = maxBytes;
18
+ }
19
+ /** Representation bytes still available for the current inspection. */
20
+ get remainingBytes() {
21
+ return this.#remainingBytes;
22
+ }
23
+ /** Representation bytes reserved so far. */
24
+ get usedBytes() {
25
+ return this.#initialBytes - this.#remainingBytes;
26
+ }
27
+ /** Reserve representation bytes before allocation, or report exhaustion. */
28
+ reserve(bytes, message) {
29
+ if (!Number.isSafeInteger(bytes) ||
30
+ bytes < 0 ||
31
+ bytes > this.#remainingBytes)
32
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", message);
33
+ this.#remainingBytes -= bytes;
34
+ }
35
+ /** Reserve an upper bound for one JSON-serialized string occurrence. */
36
+ reserveJsonStringOccurrence(value) {
37
+ // JSON escaping uses at most six ASCII bytes per UTF-16 code unit, plus
38
+ // quotes. Count occurrences even when the source string is shared.
39
+ this.reserve(value.length * 6 + 2, "projected JSON strings exceed the aggregate Interface Builder decode budget");
40
+ }
41
+ /** Reserve the exact JSON string length for a base64 value from Buffer. */
42
+ reserveBase64JsonStringOccurrence(value) {
43
+ // Buffer's base64 alphabet contains no JSON-escaped characters.
44
+ this.reserve(value.length + 2, "projected NIB base64 values exceed the aggregate Interface Builder decode budget");
45
+ }
46
+ /** Reserve an upper bound for one JSON object property name occurrence. */
47
+ reserveJsonPropertyNameOccurrence(value) {
48
+ this.reserve(value.length * 6 + 3, "projected JSON property names exceed the aggregate Interface Builder decode budget");
49
+ }
50
+ /** Reserve bytes for an optional projection without throwing on exhaustion. */
51
+ tryReserve(bytes) {
52
+ if (!Number.isSafeInteger(bytes) ||
53
+ bytes < 0 ||
54
+ bytes > this.#remainingBytes)
55
+ return false;
56
+ this.#remainingBytes -= bytes;
57
+ return true;
58
+ }
59
+ }
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"
63
+ ? estimateBinaryPlistExpansion(bytes, maxBytes)
64
+ : estimateXmlPlistExpansion(bytes, maxBytes, xmlText);
65
+ if (estimate > maxBytes)
66
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "plist representation exceeds the aggregate Interface Builder decode budget");
67
+ return estimate;
68
+ };
69
+ const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
70
+ const xml = xmlText ?? decodeXmlPlistText(bytes);
71
+ if (/<!DOCTYPE\b[^>]*\[/iu.test(xml))
72
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "XML plist internal entity expansion exceeds the aggregate Interface Builder decode budget");
73
+ const elementPattern = /<!--[^]*?-->|<!\[CDATA\[[^]*?\]\]>|<!DOCTYPE[^>]*>|<\?[^]*?\?>|<\/?[A-Za-z][^>]*>/giu;
74
+ const decodedSourceBytes = xml.length * 2;
75
+ let elementCount = 0;
76
+ let xmlDepth = 0;
77
+ for (const match of xml.matchAll(elementPattern)) {
78
+ const token = match[0] ?? "";
79
+ if (token.startsWith("<!--") ||
80
+ token.startsWith("<![CDATA[") ||
81
+ token.startsWith("<!DOCTYPE") ||
82
+ token.startsWith("<?"))
83
+ continue;
84
+ elementCount += 1;
85
+ if (token.startsWith("</"))
86
+ xmlDepth -= 1;
87
+ else if (!token.endsWith("/>")) {
88
+ xmlDepth += 1;
89
+ if (xmlDepth > 128)
90
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "XML plist nesting exceeds the aggregate Interface Builder decode budget");
91
+ }
92
+ if (decodedSourceBytes * 2 + elementCount * 128 > maxBytes)
93
+ return maxBytes + 1;
94
+ }
95
+ return decodedSourceBytes * 2 + elementCount * 128;
96
+ };
97
+ /** Count every expanded binary-plist reference before calling plist.parseBinary. */
98
+ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
99
+ if (bytes.length < 40)
100
+ throw new TypeError("binary plist trailer is truncated");
101
+ const trailer = bytes.length - 32;
102
+ const offsetSize = bytes[trailer + 6] ?? 0;
103
+ const referenceSize = bytes[trailer + 7] ?? 0;
104
+ if (![1, 2, 4, 8].includes(offsetSize) ||
105
+ ![1, 2, 4, 8].includes(referenceSize))
106
+ throw new TypeError("binary plist trailer integer sizes are invalid");
107
+ const readInteger = (offset, size) => {
108
+ if (offset < 0 || size < 1 || offset + size > bytes.length)
109
+ return -1;
110
+ let value = 0;
111
+ for (let index = 0; index < size; index += 1)
112
+ value = value * 256 + (bytes[offset + index] ?? 0);
113
+ return Number.isSafeInteger(value) ? value : -1;
114
+ };
115
+ const objectCount = readInteger(trailer + 8, 8);
116
+ const topObject = readInteger(trailer + 16, 8);
117
+ const offsetTable = readInteger(trailer + 24, 8);
118
+ if (objectCount < 1 ||
119
+ topObject < 0 ||
120
+ topObject >= objectCount ||
121
+ offsetTable < 8 ||
122
+ offsetTable + objectCount * offsetSize > trailer)
123
+ throw new TypeError("binary plist trailer or object table is invalid");
124
+ let estimate = bytes.length * 2 + objectCount * 16;
125
+ if (estimate > maxBytes)
126
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist object table exceeds the aggregate Interface Builder decode budget");
127
+ const active = new Set();
128
+ const pending = [
129
+ { object: topObject, depth: 0, exit: false },
130
+ ];
131
+ let pendingObjectCount = 1;
132
+ while (pending.length > 0) {
133
+ const entry = pending.pop();
134
+ if (entry === undefined)
135
+ break;
136
+ if (entry.exit) {
137
+ active.delete(entry.object);
138
+ continue;
139
+ }
140
+ pendingObjectCount -= 1;
141
+ if (entry.depth > 128)
142
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist nesting exceeds the aggregate Interface Builder decode budget");
143
+ if (active.has(entry.object))
144
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference cycle exceeds the aggregate Interface Builder decode budget");
145
+ estimate += 96;
146
+ if (estimate > maxBytes)
147
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
148
+ const offset = readInteger(offsetTable + entry.object * offsetSize, offsetSize);
149
+ if (offset < 8 || offset >= offsetTable)
150
+ throw new TypeError("binary plist object offset is invalid");
151
+ const marker = bytes[offset] ?? 0;
152
+ const type = marker >> 4;
153
+ let size = marker & 0x0f;
154
+ let cursor = offset + 1;
155
+ if (size === 0x0f && type !== 0 && type !== 8) {
156
+ const extMarker = bytes[cursor] ?? 0;
157
+ if (extMarker >> 4 !== 1 || (extMarker & 0x0f) > 3)
158
+ throw new TypeError("binary plist extended object size is invalid");
159
+ cursor += 1;
160
+ const integerSize = 1 << (extMarker & 0x0f);
161
+ size = readInteger(cursor, integerSize);
162
+ cursor += integerSize;
163
+ if (size < 0 || cursor > offsetTable)
164
+ throw new TypeError("binary plist extended object size is invalid");
165
+ }
166
+ if (type === 4 || type === 5 || type === 6) {
167
+ const byteLength = type === 6 ? size * 2 : size;
168
+ if (cursor + byteLength > offsetTable)
169
+ throw new TypeError("binary plist scalar object is truncated");
170
+ estimate += type === 4 ? size + 4 * Math.ceil(size / 3) : byteLength * 2;
171
+ if (estimate > maxBytes)
172
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist scalar expansion exceeds the aggregate Interface Builder decode budget");
173
+ continue;
174
+ }
175
+ if (type !== 10 && type !== 13)
176
+ continue;
177
+ const childCount = type === 13 ? size * 2 : size;
178
+ const refsEnd = cursor + childCount * referenceSize;
179
+ if (!Number.isSafeInteger(refsEnd) || refsEnd > offsetTable)
180
+ throw new TypeError("binary plist reference table is truncated");
181
+ const availableNodes = Math.floor((maxBytes - estimate) / 96);
182
+ if (childCount > availableNodes - pendingObjectCount)
183
+ throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "binary plist reference expansion exceeds the aggregate Interface Builder decode budget");
184
+ active.add(entry.object);
185
+ pending.push({ object: entry.object, depth: entry.depth, exit: true });
186
+ for (let index = childCount - 1; index >= 0; index -= 1) {
187
+ const reference = readInteger(cursor + index * referenceSize, referenceSize);
188
+ if (reference < 0 || reference >= objectCount)
189
+ throw new TypeError("binary plist reference is invalid");
190
+ pending.push({ object: reference, depth: entry.depth + 1, exit: false });
191
+ }
192
+ pendingObjectCount += childCount;
193
+ }
194
+ return estimate;
195
+ };