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
@@ -1,6 +1,6 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
- import { createSystemProcessOwnershipHost, errorMessage, } from "./ProcessOwnershipObservation.js";
3
+ import { errorMessage, systemProcessOwnershipHost as systemHost, } from "./ProcessOwnershipObservation.js";
4
4
  import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
5
5
  import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
6
6
  const execFileAsync = promisify(execFile);
@@ -28,7 +28,6 @@ export const cleanupWindowsProcessTree = async (rootPid, host = systemWindowsPro
28
28
  };
29
29
  }
30
30
  };
31
- const systemHost = createSystemProcessOwnershipHost();
32
31
  const systemWindowsProcessTreeHost = {
33
32
  async terminateTree(rootPid) {
34
33
  try {
@@ -59,7 +58,7 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
59
58
  return plan;
60
59
  let signaled = false;
61
60
  for (const processGroupId of plan.signalOrder) {
62
- const revalidation = await revalidateOwnedProcessGroup(processGroupId, ownership, host);
61
+ const revalidation = await revalidateOwnedProcessGroup(processGroupId, ownership, host, plan.tokenOwnedIdentities);
63
62
  if ("cleaned" in revalidation)
64
63
  return revalidation;
65
64
  if (revalidation.empty)
@@ -77,22 +76,36 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
77
76
  };
78
77
  }
79
78
  }
80
- return { cleaned: true, signaled };
79
+ if (plan.unresolved.length > 0)
80
+ return cleanupValidationFailure(plan.unresolved, plan.unverified);
81
+ return {
82
+ cleaned: true,
83
+ signaled,
84
+ ...(plan.unverified.length === 0 ? {} : { unverified: plan.unverified }),
85
+ };
81
86
  };
82
87
  /** Verify that no live process still carries an owned capture run token. */
83
- export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost) => {
88
+ export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost, captureBaseline, relation) => {
84
89
  const processTable = await readLiveProcessTable(host);
85
90
  if (!processTable.available)
86
91
  return {
87
92
  cleaned: false,
88
93
  reason: `process table could not be inspected: ${processTable.reason}`,
89
94
  };
90
- const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host);
95
+ const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host, captureBaseline, relation);
91
96
  if (scan.failures.length > 0)
92
- return cleanupValidationFailure(scan.failures);
93
- return scan.owned.length === 0
94
- ? { cleaned: true, signaled: false }
95
- : { cleaned: false, reason: "token-owned process remained after cleanup" };
97
+ return cleanupValidationFailure(scan.failures, scan.unverified);
98
+ if (scan.owned.length > 0)
99
+ return {
100
+ cleaned: false,
101
+ reason: "token-owned process remained after cleanup",
102
+ ...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
103
+ };
104
+ return {
105
+ cleaned: true,
106
+ signaled: false,
107
+ ...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
108
+ };
96
109
  };
97
110
  const readLiveProcessTable = async (host) => {
98
111
  try {
@@ -106,18 +119,37 @@ const readLiveProcessTable = async (host) => {
106
119
  }
107
120
  };
108
121
  const createOwnedCleanupPlan = async (ownership, processes, host) => {
122
+ const sampledProcessGroupIds = new Set((ownership.sampledProcessGroupIds ?? []).filter((processGroupId) => Number.isSafeInteger(processGroupId) && processGroupId > 0));
109
123
  const tokenOwned = ownership.sweepTokenOwnedProcesses === true
110
- ? await scanTokenOwnedProcesses(processes, ownership.runId, host)
111
- : { owned: [], failures: [] };
112
- if (tokenOwned.failures.length > 0)
113
- return cleanupValidationFailure(tokenOwned.failures);
124
+ ? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline, {
125
+ leaderPid: ownership.leaderPid,
126
+ processGroupId: ownership.processGroupId,
127
+ ...(sampledProcessGroupIds.size === 0
128
+ ? {}
129
+ : { sampledProcessGroupIds: [...sampledProcessGroupIds] }),
130
+ })
131
+ : { owned: [], failures: [], unverified: [], identities: new Map() };
114
132
  const tokenOwnedGroupIds = new Set(tokenOwned.owned.map(({ processGroupId }) => processGroupId));
115
133
  const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
116
134
  const rootMembers = processes.filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
117
135
  if (launcher === undefined &&
118
136
  rootMembers.length === 0 &&
119
- tokenOwned.owned.length === 0)
120
- return { cleaned: true, signaled: false };
137
+ tokenOwned.owned.length === 0 &&
138
+ !processes.some(({ processGroupId }) => sampledProcessGroupIds.has(processGroupId)))
139
+ return tokenOwned.failures.length > 0
140
+ ? {
141
+ signalOrder: [],
142
+ tokenOwnedIdentities: tokenOwned.identities,
143
+ unresolved: tokenOwned.failures,
144
+ unverified: tokenOwned.unverified,
145
+ }
146
+ : {
147
+ cleaned: true,
148
+ signaled: false,
149
+ ...(tokenOwned.unverified.length === 0
150
+ ? {}
151
+ : { unverified: tokenOwned.unverified }),
152
+ };
121
153
  let descendants = [];
122
154
  if (launcher !== undefined) {
123
155
  const identityFailure = launcherIdentityFailure(launcher, ownership);
@@ -131,28 +163,62 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
131
163
  processGroupIds.add(descendant.processGroupId);
132
164
  for (const process of tokenOwned.owned)
133
165
  processGroupIds.add(process.processGroupId);
166
+ for (const processGroupId of sampledProcessGroupIds)
167
+ processGroupIds.add(processGroupId);
168
+ const signalableGroups = new Set();
169
+ const unresolved = [...tokenOwned.failures];
170
+ const unverifiableSampledGroups = new Set();
134
171
  for (const processGroupId of processGroupIds) {
135
172
  if (processGroupId === ownership.processGroupId)
136
173
  continue;
137
174
  const groupLeader = processes.find(({ pid, processGroupId: observedGroupId }) => pid === processGroupId && observedGroupId === processGroupId);
138
175
  if ((groupLeader === undefined || !descendantPids.has(groupLeader.pid)) &&
139
- !tokenOwnedGroupIds.has(processGroupId))
176
+ !tokenOwnedGroupIds.has(processGroupId) &&
177
+ !sampledProcessGroupIds.has(processGroupId))
140
178
  return {
141
179
  cleaned: false,
142
180
  reason: "descendant process-group leader identity could not be verified",
143
181
  };
182
+ if ((groupLeader === undefined || !descendantPids.has(groupLeader.pid)) &&
183
+ !tokenOwnedGroupIds.has(processGroupId))
184
+ unverifiableSampledGroups.add(processGroupId);
144
185
  }
145
186
  const liveMembers = processes.filter(({ processGroupId }) => processGroupIds.has(processGroupId));
146
- const failures = await processOwnershipFailures(liveMembers, ownership.runId, host);
147
- if (failures.length > 0)
148
- return cleanupValidationFailure(failures);
187
+ for (const processGroupId of processGroupIds) {
188
+ const members = liveMembers.filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
189
+ if (members.length === 0)
190
+ continue;
191
+ const failures = await processOwnershipFailures(members, ownership.runId, host, tokenOwned.identities);
192
+ if (failures.length === 0 && unverifiableSampledGroups.has(processGroupId))
193
+ unresolved.push(...members.map(({ pid }) => ({
194
+ pid,
195
+ reason: "process-identity-unavailable",
196
+ diagnostic: "sampled process-group leader identity could not be verified",
197
+ })));
198
+ const scanFailures = tokenOwned.failures.filter(({ pid }) => members.some((member) => member.pid === pid));
199
+ if (failures.length > 0)
200
+ unresolved.push(...failures);
201
+ if (failures.length === 0 &&
202
+ scanFailures.length === 0 &&
203
+ !unverifiableSampledGroups.has(processGroupId))
204
+ signalableGroups.add(processGroupId);
205
+ }
206
+ if (ownership.sweepTokenOwnedProcesses !== true && unresolved.length > 0)
207
+ return cleanupValidationFailure(unresolved, tokenOwned.unverified);
149
208
  return {
150
- signalOrder: [ownership.processGroupId].concat([...processGroupIds]
151
- .filter((processGroupId) => processGroupId !== ownership.processGroupId)
152
- .sort((left, right) => left - right)),
209
+ signalOrder: [...signalableGroups]
210
+ .filter((groupId) => processGroupIds.has(groupId))
211
+ .sort((left, right) => left === ownership.processGroupId
212
+ ? -1
213
+ : right === ownership.processGroupId
214
+ ? 1
215
+ : left - right),
216
+ tokenOwnedIdentities: tokenOwned.identities,
217
+ unresolved,
218
+ unverified: tokenOwned.unverified,
153
219
  };
154
220
  };
155
- const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
221
+ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expectedIdentities) => {
156
222
  let members;
157
223
  try {
158
224
  members = liveProcesses(await host.listProcesses()).filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
@@ -163,7 +229,7 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
163
229
  reason: `process ownership could not be revalidated: ${errorMessage(cause)}`,
164
230
  };
165
231
  }
166
- const failures = await processOwnershipFailures(members, ownership.runId, host);
232
+ const failures = await processOwnershipFailures(members, ownership.runId, host, expectedIdentities);
167
233
  if (failures.length > 0)
168
234
  return cleanupValidationFailure(failures);
169
235
  if (processGroupId === ownership.processGroupId) {
@@ -184,15 +250,103 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
184
250
  };
185
251
  return { empty: members.length === 0 };
186
252
  };
187
- const cleanupValidationFailure = (failures) => ({
188
- cleaned: false,
189
- reason: failures.some(({ reason }) => reason === "run-token-mismatch")
190
- ? "process tree contains an unowned or PID-reused process"
191
- : "process ownership could not be revalidated",
192
- failures,
193
- });
194
- const processOwnershipFailures = async (members, runId, host) => {
253
+ const cleanupValidationFailure = (failures, unverified = []) => {
254
+ const unverifiedEntry = unverified.length === 0 ? {} : { unverified };
255
+ const unreadable = failures.filter(({ reason }) => reason === "environment-unreadable");
256
+ if (failures.some(({ reason }) => reason === "run-token-mismatch"))
257
+ return {
258
+ cleaned: false,
259
+ reason: "process tree contains an unowned or PID-reused process",
260
+ failures,
261
+ ...unverifiedEntry,
262
+ };
263
+ if (failures.some(({ reason }) => reason === "process-identity-unavailable"))
264
+ return {
265
+ cleaned: false,
266
+ reason: "process identity could not be revalidated",
267
+ failures,
268
+ ...unverifiedEntry,
269
+ };
270
+ if (unreadable.length > 0) {
271
+ const counts = new Map();
272
+ for (const { diagnostic } of unreadable) {
273
+ const category = sanitizedTokenReadFailure(diagnostic);
274
+ counts.set(category, (counts.get(category) ?? 0) + 1);
275
+ }
276
+ const breakdown = [...counts]
277
+ .sort(([left], [right]) => left.localeCompare(right))
278
+ .map(([category, count]) => `${category}=${String(count)}`)
279
+ .join(", ");
280
+ const candidates = unreadable
281
+ .map(({ pid, diagnostic }) => `${String(pid)}=${sanitizedTokenReadFailure(diagnostic)}`)
282
+ .sort((left, right) => left.localeCompare(right));
283
+ return {
284
+ cleaned: false,
285
+ reason: `process ownership token could not be read for ${String(unreadable.length)} live process(es): ${breakdown}; live candidates ${candidates.join(", ")}`,
286
+ failures,
287
+ ...unverifiedEntry,
288
+ };
289
+ }
290
+ return {
291
+ cleaned: false,
292
+ reason: "process ownership could not be revalidated",
293
+ failures,
294
+ ...unverifiedEntry,
295
+ };
296
+ };
297
+ const sanitizedTokenReadFailure = (diagnostic) => {
298
+ if (diagnostic === "environment_unavailable")
299
+ return diagnostic;
300
+ if (diagnostic === "platform_binary_environment_withheld")
301
+ return diagnostic;
302
+ const environmentErrno = /^(EACCES|EPERM|ENOENT|ESRCH):/u.exec(diagnostic ?? "");
303
+ if (environmentErrno?.[1] !== undefined)
304
+ return `environment_errno_${environmentErrno[1]}`;
305
+ if (diagnostic === "apple_vector_unavailable")
306
+ return diagnostic;
307
+ if (diagnostic === "ambiguous_environment_boundary")
308
+ return diagnostic;
309
+ if (diagnostic === "malformed_procargs")
310
+ return diagnostic;
311
+ if (diagnostic === "process_identity_changed_during_token_read")
312
+ return diagnostic;
313
+ if (diagnostic === "process_not_in_snapshot")
314
+ return diagnostic;
315
+ const processTableFailure = /^process_table_failed_(\d+)$/u.exec(diagnostic ?? "");
316
+ if (processTableFailure?.[1] !== undefined)
317
+ return `process_table_errno_${processTableFailure[1]}`;
318
+ const sysctlFailure = /^sysctl_failed_(\d+)$/u.exec(diagnostic ?? "");
319
+ if (sysctlFailure?.[1] !== undefined)
320
+ return `sysctl_errno_${sysctlFailure[1]}`;
321
+ if (diagnostic === "reader_failure")
322
+ return diagnostic;
323
+ if (diagnostic === "duplicate_run_token")
324
+ return diagnostic;
325
+ if (diagnostic === "invalid_run_token_encoding")
326
+ return diagnostic;
327
+ return "other_unavailable";
328
+ };
329
+ const processOwnershipFailures = async (members, runId, host, expectedIdentities = new Map()) => {
195
330
  const failures = [];
331
+ if (expectedIdentities.size > 0 && host.processIdentities !== undefined) {
332
+ const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
333
+ const observed = await host.processIdentities(expectedMembers);
334
+ for (const member of expectedMembers) {
335
+ const expected = expectedIdentities.get(member.pid);
336
+ const current = observed.get(member.pid);
337
+ if (expected === null ||
338
+ current?.state !== "readable" ||
339
+ current.identity !== expected) {
340
+ if (await processIsGone(host, member.pid))
341
+ continue;
342
+ failures.push({
343
+ pid: member.pid,
344
+ reason: "process-identity-unavailable",
345
+ diagnostic: "process identity changed or became unavailable before signal",
346
+ });
347
+ }
348
+ }
349
+ }
196
350
  for (const member of members) {
197
351
  try {
198
352
  if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !== runId)
@@ -219,36 +373,262 @@ const processOwnershipFailures = async (members, runId, host) => {
219
373
  });
220
374
  }
221
375
  }
376
+ if (failures.length === 0 &&
377
+ expectedIdentities.size > 0 &&
378
+ host.processIdentities !== undefined) {
379
+ const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
380
+ const observed = await host.processIdentities(expectedMembers);
381
+ for (const member of expectedMembers) {
382
+ const expected = expectedIdentities.get(member.pid);
383
+ const current = observed.get(member.pid);
384
+ if (expected !== null &&
385
+ current?.state === "readable" &&
386
+ current.identity === expected)
387
+ continue;
388
+ if (await processIsGone(host, member.pid))
389
+ continue;
390
+ failures.push({
391
+ pid: member.pid,
392
+ reason: "process-identity-unavailable",
393
+ diagnostic: "process identity changed or became unavailable during token validation",
394
+ });
395
+ }
396
+ }
222
397
  return failures;
223
398
  };
224
- const scanTokenOwnedProcesses = async (processes, runId, host) => {
225
- const owned = [];
226
- const failures = [];
227
- for (const process of processes) {
228
- try {
229
- if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
230
- owned.push(process);
399
+ const TOKEN_READ_RETRY_ATTEMPTS = 3;
400
+ const TOKEN_READ_RETRY_DELAY_MS = 40;
401
+ /** Darwin reports this when the kernel withholds a platform binary's environment. */
402
+ const PLATFORM_BINARY_ENVIRONMENT_WITHHELD = "platform_binary_environment_withheld";
403
+ const currentProcessUid = () => typeof process.getuid === "function" ? process.getuid() : undefined;
404
+ /**
405
+ * Whether the operating system provably withheld this candidate's run token:
406
+ * current macOS omits the environment of Apple platform binaries from
407
+ * KERN_PROCARGS2 and fails with EINVAL for processes owned by another
408
+ * account, and neither class can be token-verified by any caller. Such a
409
+ * candidate is recorded as unverified instead of failing an otherwise clean
410
+ * capture; every other unreadable candidate stays fail-closed.
411
+ */
412
+ const environmentWithheldFromInspection = (entry, diagnostic) => {
413
+ const uid = currentProcessUid();
414
+ if (uid !== undefined && entry.uid !== undefined && entry.uid !== uid)
415
+ return true;
416
+ return diagnostic === PLATFORM_BINARY_ENVIRONMENT_WITHHELD;
417
+ };
418
+ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline, relation) => {
419
+ let candidates = processes;
420
+ let candidateIdentities = new Map();
421
+ if (host.processIdentities !== undefined) {
422
+ const current = await host.processIdentities(processes);
423
+ candidateIdentities = current;
424
+ if (captureBaseline !== undefined) {
425
+ const baseline = new Map(captureBaseline.map(({ pid, identity }) => [pid, identity]));
426
+ candidates = processes.filter((process) => {
427
+ const before = baseline.get(process.pid);
428
+ const now = current.get(process.pid);
429
+ return !(before !== undefined &&
430
+ before !== null &&
431
+ now?.state === "readable" &&
432
+ now.identity === before);
433
+ });
231
434
  }
232
- catch (cause) {
233
- try {
234
- const live = liveProcesses(await host.listProcesses());
235
- if (!live.some(({ pid }) => pid === process.pid))
236
- continue;
435
+ }
436
+ const failures = [];
437
+ if (captureBaseline !== undefined && host.processIdentities !== undefined) {
438
+ const stableCandidates = [];
439
+ for (const process of candidates) {
440
+ if (candidateIdentities.get(process.pid)?.state === "readable") {
441
+ stableCandidates.push(process);
442
+ continue;
237
443
  }
238
- catch (recheckCause) {
444
+ if (!(await processIsGone(host, process.pid)))
239
445
  failures.push({
240
446
  pid: process.pid,
241
- reason: "environment-unreadable",
242
- diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
447
+ reason: "process-identity-unavailable",
448
+ diagnostic: "process identity was unavailable during token scan",
243
449
  });
450
+ }
451
+ candidates = stableCandidates;
452
+ }
453
+ const owned = [];
454
+ const ownedIdentities = new Map();
455
+ const recordOwned = (process) => {
456
+ owned.push(process);
457
+ const identity = candidateIdentities.get(process.pid);
458
+ ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
459
+ };
460
+ let bulkTokens;
461
+ if (host.runTokens !== undefined)
462
+ bulkTokens = await host.runTokens(candidates);
463
+ const unreadable = [];
464
+ for (const process of candidates) {
465
+ const bulkToken = bulkTokens?.get(process.pid);
466
+ if (bulkToken !== undefined) {
467
+ if (bulkToken.state === "readable") {
468
+ if (bulkToken.runId === runId)
469
+ recordOwned(process);
470
+ continue;
471
+ }
472
+ unreadable.push({ process, diagnostic: bulkToken.reason });
473
+ continue;
474
+ }
475
+ try {
476
+ if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
477
+ recordOwned(process);
478
+ }
479
+ catch (cause) {
480
+ unreadable.push({ process, diagnostic: errorMessage(cause) });
481
+ }
482
+ }
483
+ const remaining = await settleUnreadableTokenCandidates(unreadable, runId, host, recordOwned);
484
+ const relatedPids = new Set();
485
+ const relatedGroupIds = new Set();
486
+ if (relation !== undefined) {
487
+ relatedPids.add(relation.leaderPid);
488
+ for (const descendant of descendantsOf(relation.leaderPid, processes))
489
+ relatedPids.add(descendant.pid);
490
+ relatedGroupIds.add(relation.processGroupId);
491
+ for (const processGroupId of relation.sampledProcessGroupIds ?? [])
492
+ if (Number.isSafeInteger(processGroupId) && processGroupId > 0)
493
+ relatedGroupIds.add(processGroupId);
494
+ for (const process of owned)
495
+ relatedGroupIds.add(process.processGroupId);
496
+ }
497
+ const unverified = [];
498
+ const strict = [];
499
+ const withheld = [];
500
+ for (const candidate of remaining) {
501
+ const isRelated = relation === undefined ||
502
+ relatedPids.has(candidate.process.pid) ||
503
+ relatedGroupIds.has(candidate.process.processGroupId);
504
+ if (!isRelated &&
505
+ environmentWithheldFromInspection(candidate.process, candidate.diagnostic)) {
506
+ withheld.push(candidate);
507
+ continue;
508
+ }
509
+ strict.push(candidate);
510
+ }
511
+ let finalLive;
512
+ try {
513
+ finalLive = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
514
+ }
515
+ catch (cause) {
516
+ void cause;
517
+ finalLive = undefined;
518
+ }
519
+ for (const candidate of strict) {
520
+ if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
521
+ continue;
522
+ failures.push({
523
+ pid: candidate.process.pid,
524
+ reason: "environment-unreadable",
525
+ diagnostic: candidate.diagnostic,
526
+ });
527
+ }
528
+ for (const candidate of withheld) {
529
+ if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
530
+ continue;
531
+ unverified.push({
532
+ pid: candidate.process.pid,
533
+ diagnostic: candidate.diagnostic,
534
+ });
535
+ }
536
+ if (candidates.length > 0 && host.processIdentities !== undefined) {
537
+ const afterRead = await host.processIdentities(candidates);
538
+ const stillOwned = [];
539
+ const ownedPids = new Set(owned.map(({ pid }) => pid));
540
+ for (const process of candidates) {
541
+ const before = candidateIdentities.get(process.pid);
542
+ const current = afterRead.get(process.pid);
543
+ if (before?.state === "readable" &&
544
+ current?.state === "readable" &&
545
+ current.identity === before.identity) {
546
+ if (ownedPids.has(process.pid))
547
+ stillOwned.push(process);
244
548
  continue;
245
549
  }
550
+ if (await processIsGone(host, process.pid))
551
+ continue;
246
552
  failures.push({
247
553
  pid: process.pid,
248
- reason: "environment-unreadable",
249
- diagnostic: errorMessage(cause),
554
+ reason: "process-identity-unavailable",
555
+ diagnostic: "process identity changed or became unavailable during token validation",
250
556
  });
251
557
  }
558
+ return {
559
+ owned: stillOwned,
560
+ failures,
561
+ unverified,
562
+ identities: ownedIdentities,
563
+ };
564
+ }
565
+ return { owned, failures, unverified, identities: ownedIdentities };
566
+ };
567
+ /**
568
+ * Re-read run tokens for unresolved sweep candidates so transient exec and
569
+ * exit states settle before classification. Each attempt revalidates
570
+ * liveness, refreshes the diagnostic, and is bounded by a fixed attempt
571
+ * budget; a still-unreadable candidate keeps its latest diagnostic.
572
+ */
573
+ const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned) => {
574
+ let remaining = pending;
575
+ for (let attempt = 0; attempt < TOKEN_READ_RETRY_ATTEMPTS && remaining.length > 0; attempt += 1) {
576
+ await new Promise((resolve) => setTimeout(resolve, TOKEN_READ_RETRY_DELAY_MS));
577
+ let live;
578
+ try {
579
+ live = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
580
+ }
581
+ catch (cause) {
582
+ void cause;
583
+ live = undefined;
584
+ }
585
+ let observations;
586
+ if (host.runTokens !== undefined) {
587
+ try {
588
+ observations = await host.runTokens(remaining.map(({ process }) => process));
589
+ }
590
+ catch (cause) {
591
+ void cause;
592
+ observations = undefined;
593
+ }
594
+ }
595
+ const stillUnreadable = [];
596
+ for (const candidate of remaining) {
597
+ const pid = candidate.process.pid;
598
+ if (live !== undefined && !live.has(pid))
599
+ continue;
600
+ const observation = observations?.get(pid) ?? (await readEnvironmentRunToken(host, pid));
601
+ if (observation.state === "readable") {
602
+ if (observation.runId === runId)
603
+ recordOwned(candidate.process);
604
+ continue;
605
+ }
606
+ stillUnreadable.push({
607
+ process: candidate.process,
608
+ diagnostic: observation.reason,
609
+ });
610
+ }
611
+ remaining = stillUnreadable;
612
+ }
613
+ return remaining;
614
+ };
615
+ const readEnvironmentRunToken = async (host, pid) => {
616
+ try {
617
+ return {
618
+ state: "readable",
619
+ runId: (await host.environment(pid)).REA_PROCESS_RUN_ID,
620
+ };
621
+ }
622
+ catch (cause) {
623
+ return { state: "unavailable", reason: errorMessage(cause) };
624
+ }
625
+ };
626
+ const processIsGone = async (host, pid) => {
627
+ try {
628
+ return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
629
+ }
630
+ catch (cause) {
631
+ void cause;
632
+ return false;
252
633
  }
253
- return { owned, failures };
254
634
  };