rea-agents 6.3.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/README.md +7 -4
  2. package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
  3. package/bridge/ghidra/ReaGhidraBridge.java +597 -209
  4. package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
  5. package/dist/adb/AdbConfiguration.js +88 -0
  6. package/dist/adb/AdbDeviceOutput.js +186 -0
  7. package/dist/adb/AdbProvider.js +1190 -0
  8. package/dist/adb/AdbShellOutput.js +309 -0
  9. package/dist/android/AndroidTargetSnapshot.js +104 -22
  10. package/dist/android/JadxConfiguration.js +44 -24
  11. package/dist/android/JadxProvider.js +51 -19
  12. package/dist/apktool/ApktoolConfiguration.js +84 -0
  13. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  14. package/dist/apktool/ApktoolProvider.js +506 -0
  15. package/dist/application/AnalysisProvider.js +8 -2
  16. package/dist/application/AppBundleExecutable.js +27 -22
  17. package/dist/application/BinaryTargetResolver.js +22 -2
  18. package/dist/application/CapabilityInventory.js +11 -1
  19. package/dist/application/ClientConfigurationDocument.js +70 -0
  20. package/dist/application/ClientConfigurationFiles.js +91 -0
  21. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  22. package/dist/application/ClientRegistrationStatus.js +66 -31
  23. package/dist/application/DirectAnalysis.js +2 -2
  24. package/dist/application/DirectAnalysisCleanup.js +1 -1
  25. package/dist/application/DirectAnalysisStatus.js +1 -1
  26. package/dist/application/Doctor.js +5 -3
  27. package/dist/application/DoctorDiagnostics.js +1 -1
  28. package/dist/application/EvidenceBundleCommands.js +6 -12
  29. package/dist/application/GeminiClientSettings.js +139 -0
  30. package/dist/application/HermesClientHome.js +115 -0
  31. package/dist/application/HopperDownload.js +39 -0
  32. package/dist/application/InvestigationProviders.js +6 -0
  33. package/dist/application/JsonFiles.js +6 -5
  34. package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
  35. package/dist/application/LinuxHopper.js +4 -12
  36. package/dist/application/MacHopper.js +172 -149
  37. package/dist/application/MipsElfAbiFlags.js +140 -0
  38. package/dist/application/ProviderOperationExecution.js +31 -0
  39. package/dist/application/ReconstructionObligationCandidates.js +9 -3
  40. package/dist/application/ReferenceSourceImport.js +76 -29
  41. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  42. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  43. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  44. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  45. package/dist/application/RegularFileRead.js +93 -7
  46. package/dist/application/Setup.js +54 -6
  47. package/dist/application/SetupClientConfiguration.js +116 -16
  48. package/dist/application/SetupHost.js +102 -24
  49. package/dist/application/SetupPlan.js +5 -8
  50. package/dist/application/SetupSkill.js +58 -39
  51. package/dist/application/SupportedClients.js +290 -65
  52. package/dist/application/Uninstall.js +158 -10
  53. package/dist/application/UpdateMaintenance.js +17 -21
  54. package/dist/application/Utf8JsonInput.js +7 -0
  55. package/dist/application/WebScriptExportService.js +131 -65
  56. package/dist/application/WebSourceLocationService.js +3 -0
  57. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  58. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  59. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  60. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  61. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  62. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  63. package/dist/application/binary/BinarySession.js +2 -1
  64. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  65. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  66. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  67. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  68. package/dist/application/evm/EvmInterfaceService.js +3 -0
  69. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  70. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  71. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  72. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  73. package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
  74. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  75. package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
  76. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  77. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
  78. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  79. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
  80. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  81. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  82. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
  83. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  84. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
  85. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
  86. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  89. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
  90. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
  91. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
  92. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
  93. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
  94. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
  95. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
  96. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  97. package/dist/application/jeb/JebAnalysisService.js +13 -0
  98. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  99. package/dist/application/native/NativeUiActionTrace.js +16 -8
  100. package/dist/application/native/NativeValueTrace.js +23 -6
  101. package/dist/application/process/ProcessCli.js +25 -20
  102. package/dist/artifacts/ArtifactPaths.js +129 -8
  103. package/dist/artifacts/ArtifactProvider.js +20 -15
  104. package/dist/artifacts/ArtifactReader.js +23 -0
  105. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  106. package/dist/artifacts/AsarArtifactReader.js +176 -102
  107. package/dist/artifacts/AsarHeader.js +24 -0
  108. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  109. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  110. package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
  111. package/dist/artifacts/SafeOutputTree.js +245 -70
  112. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  113. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  114. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  115. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  116. package/dist/artifacts/ZipArtifactReader.js +77 -27
  117. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  118. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  119. package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
  120. package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
  121. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
  122. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  123. package/dist/artifacts/inventory/classify.js +75 -32
  124. package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
  125. package/dist/artifacts/inventory/reader.js +13 -5
  126. package/dist/artifacts/inventory/scanCanonical.js +62 -25
  127. package/dist/artifacts/inventory/scanReader.js +38 -11
  128. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
  129. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  130. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  131. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  132. package/dist/browser/CdpBrowserProvider.js +5 -0
  133. package/dist/browser/CdpCaptureDocuments.js +40 -6
  134. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  135. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  136. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  137. package/dist/browser/CdpCaptureEvents.js +4 -9
  138. package/dist/browser/CdpConnection.js +22 -5
  139. package/dist/browser/CdpPageCapture.js +1 -1
  140. package/dist/browser/CdpTargetSession.js +30 -34
  141. package/dist/browser/CdpWebMcpDiscovery.js +32 -10
  142. package/dist/browser/ElectronFileScope.js +99 -9
  143. package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
  144. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  145. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  146. package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
  147. package/dist/browser/PlaywrightScenarioSession.js +127 -54
  148. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  149. package/dist/browser/PngVisualDiff.js +198 -29
  150. package/dist/browser/WebSourceMapFetcher.js +3 -3
  151. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  152. package/dist/browser/assets/PublishWebScripts.js +75 -20
  153. package/dist/browser/assets/WebArtifactReads.js +23 -1
  154. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  155. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  156. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  157. package/dist/browser/history/HarCapture.js +14 -0
  158. package/dist/browser/history/HarCaptureProcess.js +2 -10
  159. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  160. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  161. package/dist/cli/adbCommands.js +337 -0
  162. package/dist/cli/analysisViewCommands.js +39 -1
  163. package/dist/cli/apktoolCommands.js +53 -0
  164. package/dist/cli/artifactCommands.js +8 -11
  165. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  166. package/dist/cli/browserAdvancedCommands.js +65 -36
  167. package/dist/cli/coreBinaryCommands.js +0 -5
  168. package/dist/cli/coreNativeCommands.js +1 -14
  169. package/dist/cli/electronCommands.js +6 -1
  170. package/dist/cli/evmCommands.js +13 -4
  171. package/dist/cli/firmwareCommands.js +7 -2
  172. package/dist/cli/javascriptApplicationAnalysis.js +17 -1
  173. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  174. package/dist/cli/jebCommands.js +99 -0
  175. package/dist/cli/jsonOutput.js +11 -4
  176. package/dist/cli/referenceSourceImportStatus.js +7 -0
  177. package/dist/cli/setupCommands.js +15 -3
  178. package/dist/cli/utilityCommands.js +66 -18
  179. package/dist/cli/webScriptCommands.js +20 -1
  180. package/dist/cli/webSourceLocationCommands.js +21 -9
  181. package/dist/cli.js +6 -0
  182. package/dist/cliBrowserScenarioCommands.js +2 -1
  183. package/dist/cliCommandNames.js +32 -0
  184. package/dist/cliJsonInput.js +2 -2
  185. package/dist/cliObservationOptions.js +3 -0
  186. package/dist/composition/adb.js +3 -0
  187. package/dist/composition/apktool.js +3 -0
  188. package/dist/composition/binaryDiagnostics.js +4 -0
  189. package/dist/composition/directAnalysis.js +12 -4
  190. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  191. package/dist/composition/jeb.js +6 -0
  192. package/dist/config/environment.js +10 -0
  193. package/dist/config/ghidraLanguageOverride.js +9 -0
  194. package/dist/config/mcpInputSchemaProfile.js +27 -0
  195. package/dist/config/parseConfig.js +28 -1
  196. package/dist/contracts/adb/adbToolContracts.js +353 -0
  197. package/dist/contracts/advertisedInputExamples.js +48 -0
  198. package/dist/contracts/analysisDetail.js +10 -0
  199. package/dist/contracts/analysisViewToolContracts.js +17 -2
  200. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  201. package/dist/contracts/artifactToolContracts.js +8 -5
  202. package/dist/contracts/browserToolContracts.js +1 -1
  203. package/dist/contracts/compactInputSchema.js +256 -0
  204. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  205. package/dist/contracts/inputSchemaPresentation.js +10 -10
  206. package/dist/contracts/javascript/electronToolContracts.js +15 -3
  207. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  208. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  209. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  210. package/dist/contracts/officialToolContracts.js +5 -5
  211. package/dist/contracts/sessionToolContracts.js +2 -2
  212. package/dist/contracts/sessionToolSchemas.js +6 -2
  213. package/dist/contracts/toolContractExamples.js +6 -0
  214. package/dist/contracts/toolContractTypes.js +3 -0
  215. package/dist/contracts/toolContracts.js +6 -0
  216. package/dist/contracts/toolEffects.js +167 -0
  217. package/dist/contracts/toolOutputSchemaGroups.js +5 -3
  218. package/dist/contracts/toolSchemaMetadata.js +82 -7
  219. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  220. package/dist/domain/analysisErrorCleanup.js +29 -0
  221. package/dist/domain/analysisErrorPresentation.js +18 -6
  222. package/dist/domain/analysisErrorProjection.js +4 -1
  223. package/dist/domain/analysisSnapshot.js +2 -1
  224. package/dist/domain/analysisView/analysisView.js +52 -2
  225. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  226. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  227. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  228. package/dist/domain/android/androidApplication.js +25 -20
  229. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  230. package/dist/domain/apple/appleApplication.js +40 -23
  231. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  232. package/dist/domain/apple/dyldPaths.js +9 -1
  233. package/dist/domain/apple/dylibResolution.js +2 -2
  234. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  235. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  236. package/dist/domain/artifactComparison.js +35 -7
  237. package/dist/domain/artifactGraph.js +5 -3
  238. package/dist/domain/artifactIdentity.js +30 -2
  239. package/dist/domain/artifactInspection.js +3 -43
  240. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  241. package/dist/domain/artifactInventoryEvidence.js +11 -12
  242. package/dist/domain/artifactPathSyntax.js +1 -1
  243. package/dist/domain/binaryTarget.js +16 -0
  244. package/dist/domain/binaryTargetTypes.js +8 -1
  245. package/dist/domain/browserObservationSchemas.js +8 -4
  246. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  247. package/dist/domain/compactStringIdentity.js +9 -0
  248. package/dist/domain/evidence.js +2 -1
  249. package/dist/domain/evidenceRecordSummary.js +144 -0
  250. package/dist/domain/inputIssueProjection.js +16 -1
  251. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
  252. package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
  253. package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
  254. package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
  255. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  256. package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
  257. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
  258. package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
  259. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  260. package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
  261. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
  262. package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
  263. package/dist/domain/javascript/javascriptAstValues.js +32 -0
  264. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  265. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  266. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
  267. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  268. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  269. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
  270. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
  271. package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
  272. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  273. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  274. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  275. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  276. package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
  277. package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
  278. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
  279. package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
  280. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
  281. package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
  282. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  283. package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
  284. package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
  285. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
  286. package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
  287. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
  288. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  289. package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
  290. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  291. package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
  292. package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
  293. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  294. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  295. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
  296. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  297. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  298. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  299. package/dist/domain/jeb/jebAnalysis.js +114 -0
  300. package/dist/domain/jsonShape.js +63 -52
  301. package/dist/domain/jsonValue.js +3 -0
  302. package/dist/domain/managed/managedApplicationGraph.js +37 -0
  303. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  304. package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
  305. package/dist/domain/managed/managedArtifact.js +1 -0
  306. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  307. package/dist/domain/native/nativeAotPe.js +1408 -0
  308. package/dist/domain/native/nativeInstruction.js +21 -0
  309. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  310. package/dist/domain/native/peResources.js +94 -0
  311. package/dist/domain/nativeConvention.js +33 -0
  312. package/dist/domain/process/processCapture.js +91 -1
  313. package/dist/domain/process/processCaptureExample.js +24 -0
  314. package/dist/domain/process/processCaptureValidation.js +79 -0
  315. package/dist/domain/process/processScenario.js +59 -7
  316. package/dist/domain/propertyListKeys.js +3 -1
  317. package/dist/domain/referenceSourceGraph.js +25 -16
  318. package/dist/domain/referenceSourceImportParsing.js +6 -3
  319. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  320. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  321. package/dist/domain/webBundleAnalyzerInspection.js +14 -2
  322. package/dist/domain/webCaptureDiff.js +102 -4
  323. package/dist/domain/webScriptExportError.js +10 -4
  324. package/dist/domain/webScriptExportPlan.js +7 -13
  325. package/dist/domain/zipPackageFormat.js +4 -1
  326. package/dist/domain/zodCollectionSteps.js +24 -0
  327. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  328. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  329. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  330. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  331. package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
  332. package/dist/dotnet/ManagedMemberRows.js +9 -4
  333. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  334. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  335. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  336. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  337. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  338. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  339. package/dist/dotnet/ManagedPeReader.js +41 -25
  340. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  341. package/dist/dotnet/ManagedStaticProvider.js +55 -24
  342. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  343. package/dist/evaluation/CodexAgentEval.js +43 -13
  344. package/dist/evm/EvmoleFailures.js +0 -2
  345. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  346. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  347. package/dist/filesystem/OwnedFileHandle.js +36 -0
  348. package/dist/filesystem/RegularFile.js +33 -1
  349. package/dist/filesystem/StableFileHash.js +46 -0
  350. package/dist/filesystem/readFileHandleChunks.js +26 -0
  351. package/dist/firmware/FirmwareCommand.js +25 -3
  352. package/dist/firmware/FirmwareFiles.js +23 -8
  353. package/dist/firmware/FirmwareProvider.js +156 -32
  354. package/dist/firmware/FirmwarePublication.js +24 -3
  355. package/dist/firmware/FirmwareRelease.js +1 -0
  356. package/dist/generatedPackageMetadata.js +2 -2
  357. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  358. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  359. package/dist/ghidra/GhidraClient.js +76 -4
  360. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  361. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  362. package/dist/ghidra/GhidraInstallation.js +1 -1
  363. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  364. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  365. package/dist/ghidra/GhidraLauncher.js +80 -39
  366. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  367. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  368. package/dist/ghidra/GhidraProvider.js +57 -9
  369. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  370. package/dist/ghidra/GhidraProviderClient.js +282 -21
  371. package/dist/ghidra/GhidraSessionValues.js +9 -2
  372. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  373. package/dist/hopper/HopperClient.js +15 -6
  374. package/dist/hopper/HopperMachOImage.js +2 -0
  375. package/dist/hopper/HopperProvider.js +13 -2
  376. package/dist/ida/IdaOperationRunner.js +8 -2
  377. package/dist/ida/IdaProvider.js +7 -0
  378. package/dist/ida/IdaSessionClient.js +3 -1
  379. package/dist/ida/IdaWorkspace.js +4 -2
  380. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  381. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  382. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  383. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  384. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  385. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  386. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  387. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  388. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  389. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  390. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  391. package/dist/javascript/recovery/WakaruReport.js +12 -7
  392. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  393. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  394. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  395. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  396. package/dist/jeb/JebMcpConnection.js +179 -0
  397. package/dist/jeb/JebMcpEndpoint.js +40 -0
  398. package/dist/jeb/JebProvider.js +299 -0
  399. package/dist/mcpDoctor.js +15 -6
  400. package/dist/native/AppleDispatchCoverage.js +25 -12
  401. package/dist/native/AppleDispatchMetadata.js +14 -7
  402. package/dist/native/AppleMachoFixups.js +71 -15
  403. package/dist/native/AppleMachoSelection.js +23 -3
  404. package/dist/native/NativeMacOSProvider.js +91 -16
  405. package/dist/native/NativeMachoInspection.js +11 -7
  406. package/dist/native/NativeUiHelperRuntime.js +6 -1
  407. package/dist/native/NativeUiObservation.js +4 -3
  408. package/dist/native/pe/PeResourceLayout.js +120 -0
  409. package/dist/native/pe/PeResourceParser.js +286 -0
  410. package/dist/native/pe/PeResourcesProvider.js +63 -0
  411. package/dist/process/BoundedFileBytes.js +30 -7
  412. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  413. package/dist/process/OwnedCommand.js +4 -3
  414. package/dist/process/ProcessOwnership.js +104 -112
  415. package/dist/process/ProcessOwnershipObservation.js +96 -39
  416. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  417. package/dist/process/ProcessRunTokenObservations.js +48 -0
  418. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  419. package/dist/process/ProviderProcess.js +4 -3
  420. package/dist/process/capture/FilesystemSnapshot.js +28 -4
  421. package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
  422. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  423. package/dist/process/capture/ProcessHarness.js +194 -26
  424. package/dist/process/capture/ProcessNormalization.js +3 -1
  425. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  426. package/dist/process/capture/TerminalRenderer.js +24 -7
  427. package/dist/reference/ReferenceSourceReader.js +22 -5
  428. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  429. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  430. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  431. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  432. package/dist/server/EvidenceMcpServer.js +36 -1
  433. package/dist/server/admittedToolOperation.js +9 -0
  434. package/dist/server/contractToolHandler.js +21 -0
  435. package/dist/server/createServer.js +97 -25
  436. package/dist/server/registerAdbTools.js +36 -0
  437. package/dist/server/registerAnalysisViewTool.js +4 -9
  438. package/dist/server/registerAndroidTools.js +3 -12
  439. package/dist/server/registerApktoolTools.js +14 -0
  440. package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
  441. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  442. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  443. package/dist/server/registerApplicationTools/coverage.js +3 -2
  444. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  445. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  446. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  447. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  448. package/dist/server/registerArtifactComparisonTool.js +5 -2
  449. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  450. package/dist/server/registerBrowserScenarioTool.js +10 -7
  451. package/dist/server/registerBrowserTools.js +12 -9
  452. package/dist/server/registerBundleComparisonTool.js +16 -2
  453. package/dist/server/registerCloseLifecycleTool.js +32 -3
  454. package/dist/server/registerElectronTools.js +28 -10
  455. package/dist/server/registerEvmTools.js +4 -9
  456. package/dist/server/registerFirmwareTools.js +3 -11
  457. package/dist/server/registerFunctionComparisonTool.js +5 -2
  458. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  459. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  460. package/dist/server/registerJebTools.js +16 -0
  461. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  462. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  463. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  464. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  465. package/dist/server/registerPeResourcesTool.js +9 -0
  466. package/dist/server/registerProcessComparisonTool.js +5 -2
  467. package/dist/server/registerRecordedCrashTools.js +4 -9
  468. package/dist/server/registerSessionRecordTools.js +2 -1
  469. package/dist/server/registerSessionTools.js +49 -18
  470. package/dist/server/registerWebModuleTool.js +4 -9
  471. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  472. package/dist/server/registerWebRuntimeTools.js +6 -5
  473. package/dist/server/registerWebScriptTool.js +6 -3
  474. package/dist/server/registerWebSourceLocationTool.js +4 -9
  475. package/dist/server/toolResult.js +21 -2
  476. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  477. package/install.sh +7 -4
  478. package/licenses/nativeaot-parser-MIT.txt +28 -0
  479. package/native/windows/build/manifest.json +2 -2
  480. package/native/windows/build/rea-windows-x64.node +0 -0
  481. package/package.json +33 -5
  482. package/scripts/rea.mjs +16 -1
  483. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  484. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  485. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  486. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  487. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
@@ -3,6 +3,7 @@ import { promisify } from "node:util";
3
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
+ import { readProcessRunTokens } from "./ProcessRunTokenObservations.js";
6
7
  const execFileAsync = promisify(execFile);
7
8
  /**
8
9
  * Terminate one Windows process tree through the platform utility.
@@ -115,7 +116,38 @@ const readLiveProcessTable = async (host) => {
115
116
  return { available: false, reason: errorMessage(cause) };
116
117
  }
117
118
  };
118
- const createOwnedCleanupPlan = async (ownership, processes, host) => {
119
+ // A process-table read can race exit and retain the old state with an altered
120
+ // command. Only a fresh table proving that PID is no longer live can settle
121
+ // that mismatch; surviving group members still require normal token checks.
122
+ const settleLauncherExit = async (ownership, processes, host) => {
123
+ const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
124
+ if (launcher === undefined)
125
+ return processes;
126
+ const reason = launcherIdentityFailure(launcher, ownership);
127
+ if (reason === null)
128
+ return processes;
129
+ const refreshed = await readLiveProcessTable(host);
130
+ if (refreshed.available &&
131
+ !refreshed.processes.some(({ pid }) => pid === launcher.pid)) {
132
+ // Refreshing must not discard a surviving detached descendant's lineage,
133
+ // including a child that changed groups while the launcher exited.
134
+ const descendants = descendantsOf([launcher.pid], processes);
135
+ const descendantPids = new Set(descendants.map(({ pid }) => pid));
136
+ const descendantGroupIds = new Set(descendants.map(({ processGroupId }) => processGroupId));
137
+ const refreshedDescendantPids = new Set(descendantsOf(descendants.map(({ pid }) => pid), refreshed.processes).map(({ pid }) => pid));
138
+ if (refreshed.processes.some((process) => process.processGroupId !== ownership.processGroupId &&
139
+ (refreshedDescendantPids.has(process.pid) ||
140
+ descendantPids.has(process.pid) ||
141
+ descendantGroupIds.has(process.processGroupId))))
142
+ return { cleaned: false, reason };
143
+ return refreshed.processes;
144
+ }
145
+ return { cleaned: false, reason };
146
+ };
147
+ const createOwnedCleanupPlan = async (ownership, initialProcesses, host) => {
148
+ const processes = await settleLauncherExit(ownership, initialProcesses, host);
149
+ if ("cleaned" in processes)
150
+ return processes;
119
151
  const sampledProcessGroupIds = new Set((ownership.sampledProcessGroupIds ?? []).filter((processGroupId) => Number.isSafeInteger(processGroupId) && processGroupId > 0));
120
152
  const tokenOwned = ownership.sweepTokenOwnedProcesses === true
121
153
  ? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline, {
@@ -149,10 +181,7 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
149
181
  };
150
182
  let descendants = [];
151
183
  if (launcher !== undefined) {
152
- const identityFailure = launcherIdentityFailure(launcher, ownership);
153
- if (identityFailure !== null)
154
- return { cleaned: false, reason: identityFailure };
155
- descendants = descendantsOf(launcher.pid, processes);
184
+ descendants = descendantsOf([launcher.pid], processes);
156
185
  }
157
186
  const descendantPids = new Set(descendants.map(({ pid }) => pid));
158
187
  const processGroupIds = new Set([ownership.processGroupId]);
@@ -218,7 +247,10 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
218
247
  const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expectedIdentities) => {
219
248
  let members;
220
249
  try {
221
- members = liveProcesses(await host.listProcesses()).filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
250
+ const processes = await settleLauncherExit(ownership, liveProcesses(await host.listProcesses()), host);
251
+ if ("cleaned" in processes)
252
+ return processes;
253
+ members = processes.filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
222
254
  }
223
255
  catch (cause) {
224
256
  return {
@@ -229,14 +261,6 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expe
229
261
  const failures = await processOwnershipFailures(members, ownership.runId, host, expectedIdentities);
230
262
  if (failures.length > 0)
231
263
  return cleanupValidationFailure(failures);
232
- if (processGroupId === ownership.processGroupId) {
233
- const launcher = members.find(({ pid }) => pid === ownership.leaderPid);
234
- if (launcher !== undefined) {
235
- const identityFailure = launcherIdentityFailure(launcher, ownership);
236
- if (identityFailure !== null)
237
- return { cleaned: false, reason: identityFailure };
238
- }
239
- }
240
264
  if (processGroupId !== ownership.processGroupId &&
241
265
  members.length > 0 &&
242
266
  !members.some(({ pid }) => pid === processGroupId) &&
@@ -328,53 +352,29 @@ const processOwnershipFailures = async (members, runId, host, expectedIdentities
328
352
  if (expectedIdentities.size > 0 && host.processIdentities !== undefined) {
329
353
  const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
330
354
  const observed = await host.processIdentities(expectedMembers);
355
+ const identityFailures = [];
331
356
  for (const member of expectedMembers) {
332
357
  const expected = expectedIdentities.get(member.pid);
333
358
  const current = observed.get(member.pid);
334
359
  if (expected === null ||
335
360
  current?.state !== "readable" ||
336
361
  current.identity !== expected) {
337
- if (await processIsGone(host, member.pid))
338
- continue;
339
- failures.push({
362
+ identityFailures.push({
340
363
  pid: member.pid,
341
364
  reason: "process-identity-unavailable",
342
365
  diagnostic: "process identity changed or became unavailable before signal",
343
366
  });
344
367
  }
345
368
  }
369
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
346
370
  }
347
- for (const member of members) {
348
- try {
349
- if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !== runId)
350
- failures.push({ pid: member.pid, reason: "run-token-mismatch" });
351
- }
352
- catch (cause) {
353
- try {
354
- const live = liveProcesses(await host.listProcesses());
355
- if (!live.some(({ pid }) => pid === member.pid))
356
- continue;
357
- }
358
- catch (recheckCause) {
359
- failures.push({
360
- pid: member.pid,
361
- reason: "environment-unreadable",
362
- diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
363
- });
364
- continue;
365
- }
366
- failures.push({
367
- pid: member.pid,
368
- reason: "environment-unreadable",
369
- diagnostic: errorMessage(cause),
370
- });
371
- }
372
- }
371
+ failures.push(...(await processRunTokenFailures(members, runId, host)));
373
372
  if (failures.length === 0 &&
374
373
  expectedIdentities.size > 0 &&
375
374
  host.processIdentities !== undefined) {
376
375
  const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
377
376
  const observed = await host.processIdentities(expectedMembers);
377
+ const identityFailures = [];
378
378
  for (const member of expectedMembers) {
379
379
  const expected = expectedIdentities.get(member.pid);
380
380
  const current = observed.get(member.pid);
@@ -382,17 +382,53 @@ const processOwnershipFailures = async (members, runId, host, expectedIdentities
382
382
  current?.state === "readable" &&
383
383
  current.identity === expected)
384
384
  continue;
385
- if (await processIsGone(host, member.pid))
386
- continue;
387
- failures.push({
385
+ identityFailures.push({
388
386
  pid: member.pid,
389
387
  reason: "process-identity-unavailable",
390
388
  diagnostic: "process identity changed or became unavailable during token validation",
391
389
  });
392
390
  }
391
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
393
392
  }
394
393
  return failures;
395
394
  };
395
+ const processRunTokenFailures = async (members, runId, host) => {
396
+ const failures = [];
397
+ for await (const { process: member, observation } of readProcessRunTokens(host, members)) {
398
+ if (observation.state === "readable") {
399
+ if (observation.runId !== runId)
400
+ failures.push({ pid: member.pid, reason: "run-token-mismatch" });
401
+ continue;
402
+ }
403
+ failures.push({
404
+ pid: member.pid,
405
+ reason: "environment-unreadable",
406
+ diagnostic: observation.reason,
407
+ });
408
+ }
409
+ return recheckOwnershipFailures(failures, host);
410
+ };
411
+ /**
412
+ * Take a fresh liveness snapshot after each ownership-read phase. Only an
413
+ * absent PID resolves an unreadable observation; a readable token mismatch
414
+ * remains a failure. Never reuse this snapshot across identity/token reads.
415
+ */
416
+ const recheckOwnershipFailures = async (failures, host) => {
417
+ if (!failures.some(({ reason }) => reason !== "run-token-mismatch"))
418
+ return failures;
419
+ try {
420
+ const live = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
421
+ return failures.filter(({ pid, reason }) => reason === "run-token-mismatch" || live.has(pid));
422
+ }
423
+ catch (cause) {
424
+ return failures.map((failure) => failure.reason === "run-token-mismatch"
425
+ ? failure
426
+ : {
427
+ ...failure,
428
+ diagnostic: `${failure.diagnostic}; process liveness recheck failed: ${errorMessage(cause)}`,
429
+ });
430
+ }
431
+ };
396
432
  const TOKEN_READ_RETRY_ATTEMPTS = 3;
397
433
  const TOKEN_READ_RETRY_DELAY_MS = 40;
398
434
  /** Darwin reports this when the kernel withholds a platform binary's environment. */
@@ -433,18 +469,19 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
433
469
  const failures = [];
434
470
  if (captureBaseline !== undefined && host.processIdentities !== undefined) {
435
471
  const stableCandidates = [];
472
+ const identityFailures = [];
436
473
  for (const process of candidates) {
437
474
  if (candidateIdentities.get(process.pid)?.state === "readable") {
438
475
  stableCandidates.push(process);
439
476
  continue;
440
477
  }
441
- if (!(await processIsGone(host, process.pid)))
442
- failures.push({
443
- pid: process.pid,
444
- reason: "process-identity-unavailable",
445
- diagnostic: "process identity was unavailable during token scan",
446
- });
478
+ identityFailures.push({
479
+ pid: process.pid,
480
+ reason: "process-identity-unavailable",
481
+ diagnostic: "process identity was unavailable during token scan",
482
+ });
447
483
  }
484
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
448
485
  candidates = stableCandidates;
449
486
  }
450
487
  const owned = [];
@@ -454,35 +491,21 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
454
491
  const identity = candidateIdentities.get(process.pid);
455
492
  ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
456
493
  };
457
- let bulkTokens;
458
- if (host.runTokens !== undefined)
459
- bulkTokens = await host.runTokens(candidates);
460
494
  const unreadable = [];
461
- for (const process of candidates) {
462
- const bulkToken = bulkTokens?.get(process.pid);
463
- if (bulkToken !== undefined) {
464
- if (bulkToken.state === "readable") {
465
- if (bulkToken.runId === runId)
466
- recordOwned(process);
467
- continue;
468
- }
469
- unreadable.push({ process, diagnostic: bulkToken.reason });
470
- continue;
471
- }
472
- try {
473
- if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
495
+ for await (const { process, observation } of readProcessRunTokens(host, candidates)) {
496
+ if (observation.state === "readable") {
497
+ if (observation.runId === runId)
474
498
  recordOwned(process);
475
499
  }
476
- catch (cause) {
477
- unreadable.push({ process, diagnostic: errorMessage(cause) });
478
- }
500
+ else
501
+ unreadable.push({ process, diagnostic: observation.reason });
479
502
  }
480
503
  const remaining = await settleUnreadableTokenCandidates(unreadable, runId, host, recordOwned);
481
504
  const relatedPids = new Set();
482
505
  const relatedGroupIds = new Set();
483
506
  if (relation !== undefined) {
484
507
  relatedPids.add(relation.leaderPid);
485
- for (const descendant of descendantsOf(relation.leaderPid, processes))
508
+ for (const descendant of descendantsOf([relation.leaderPid], processes))
486
509
  relatedPids.add(descendant.pid);
487
510
  relatedGroupIds.add(relation.processGroupId);
488
511
  for (const processGroupId of relation.sampledProcessGroupIds ?? [])
@@ -533,6 +556,7 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
533
556
  if (candidates.length > 0 && host.processIdentities !== undefined) {
534
557
  const afterRead = await host.processIdentities(candidates);
535
558
  const stillOwned = [];
559
+ const identityFailures = [];
536
560
  const ownedPids = new Set(owned.map(({ pid }) => pid));
537
561
  for (const process of candidates) {
538
562
  const before = candidateIdentities.get(process.pid);
@@ -544,14 +568,13 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
544
568
  stillOwned.push(process);
545
569
  continue;
546
570
  }
547
- if (await processIsGone(host, process.pid))
548
- continue;
549
- failures.push({
571
+ identityFailures.push({
550
572
  pid: process.pid,
551
573
  reason: "process-identity-unavailable",
552
574
  diagnostic: "process identity changed or became unavailable during token validation",
553
575
  });
554
576
  }
577
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
555
578
  return {
556
579
  owned: stillOwned,
557
580
  failures,
@@ -579,29 +602,18 @@ const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned
579
602
  void cause;
580
603
  live = undefined;
581
604
  }
582
- let observations;
583
- if (host.runTokens !== undefined) {
584
- try {
585
- observations = await host.runTokens(remaining.map(({ process }) => process));
586
- }
587
- catch (cause) {
588
- void cause;
589
- observations = undefined;
590
- }
591
- }
592
605
  const stillUnreadable = [];
593
- for (const candidate of remaining) {
594
- const pid = candidate.process.pid;
595
- if (live !== undefined && !live.has(pid))
596
- continue;
597
- const observation = observations?.get(pid) ?? (await readEnvironmentRunToken(host, pid));
606
+ const candidates = remaining
607
+ .map(({ process }) => process)
608
+ .filter(({ pid }) => live === undefined || live.has(pid));
609
+ for await (const { process, observation } of readProcessRunTokens(host, candidates)) {
598
610
  if (observation.state === "readable") {
599
611
  if (observation.runId === runId)
600
- recordOwned(candidate.process);
612
+ recordOwned(process);
601
613
  continue;
602
614
  }
603
615
  stillUnreadable.push({
604
- process: candidate.process,
616
+ process,
605
617
  diagnostic: observation.reason,
606
618
  });
607
619
  }
@@ -609,23 +621,3 @@ const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned
609
621
  }
610
622
  return remaining;
611
623
  };
612
- const readEnvironmentRunToken = async (host, pid) => {
613
- try {
614
- return {
615
- state: "readable",
616
- runId: (await host.environment(pid)).REA_PROCESS_RUN_ID,
617
- };
618
- }
619
- catch (cause) {
620
- return { state: "unavailable", reason: errorMessage(cause) };
621
- }
622
- };
623
- const processIsGone = async (host, pid) => {
624
- try {
625
- return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
626
- }
627
- catch (cause) {
628
- void cause;
629
- return false;
630
- }
631
- };
@@ -4,46 +4,65 @@ import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
4
4
  import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
5
5
  import { execFileOutput } from "./ExecFileOutput.js";
6
6
  import { createDarwinProcessRunTokenReader } from "./DarwinProcessRunTokenReader.js";
7
- /** Observe one group without signaling it, failing closed on identity doubt. */
8
- export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost, signal) => {
7
+ import { readProcessRunTokens } from "./ProcessRunTokenObservations.js";
8
+ /** Observe multiple groups from one process snapshot and one token batch. */
9
+ export const observeOwnedProcessGroups = async (runId, processGroupIds, host = systemProcessOwnershipHost, signal) => {
9
10
  signal?.throwIfAborted();
10
- let members;
11
+ const groupIds = [...new Set(processGroupIds)];
12
+ if (groupIds.length === 0)
13
+ return new Map();
14
+ let processes;
11
15
  try {
12
- members = (await host.listProcesses(signal)).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
16
+ processes = liveProcesses(await host.listProcesses(signal));
13
17
  }
14
18
  catch (cause) {
15
19
  signal?.throwIfAborted();
16
- return {
20
+ const failure = {
17
21
  state: "unverifiable",
18
22
  reason: `process group could not be inspected: ${errorMessage(cause)}`,
19
23
  };
24
+ return new Map(groupIds.map((groupId) => [groupId, failure]));
20
25
  }
21
26
  signal?.throwIfAborted();
22
- const liveMembers = liveProcesses(members);
23
- if (liveMembers.length === 0)
24
- return { state: "empty" };
25
- for (const member of liveMembers) {
26
- signal?.throwIfAborted();
27
- try {
28
- const runId = (await host.environment(member.pid)).REA_PROCESS_RUN_ID;
29
- signal?.throwIfAborted();
30
- if (runId !== ownership.runId)
31
- return {
27
+ const membersByGroup = new Map(groupIds.map((groupId) => [groupId, []]));
28
+ for (const process of processes)
29
+ membersByGroup.get(process.processGroupId)?.push(process);
30
+ const observations = new Map(groupIds.map((groupId) => [
31
+ groupId,
32
+ (membersByGroup.get(groupId)?.length ?? 0) > 0
33
+ ? { state: "alive" }
34
+ : { state: "empty" },
35
+ ]));
36
+ const liveMembers = groupIds.flatMap((groupId) => membersByGroup.get(groupId) ?? []);
37
+ const pendingGroups = new Set(groupIds.filter((groupId) => (membersByGroup.get(groupId)?.length ?? 0) > 0));
38
+ for await (const { process: member, observation } of readProcessRunTokens(host, liveMembers, signal)) {
39
+ if (!pendingGroups.has(member.processGroupId))
40
+ continue;
41
+ if (observation.state === "readable") {
42
+ if (observation.runId !== runId) {
43
+ observations.set(member.processGroupId, {
32
44
  state: "unverifiable",
33
45
  reason: "process ownership did not match",
34
- };
46
+ });
47
+ pendingGroups.delete(member.processGroupId);
48
+ }
35
49
  }
36
- catch (cause) {
50
+ else {
51
+ const gone = await processIsGone(host, member.pid);
37
52
  signal?.throwIfAborted();
38
- if (!(await processIsGone(host, member.pid))) {
39
- return {
53
+ if (!gone) {
54
+ observations.set(member.processGroupId, {
40
55
  state: "unverifiable",
41
- reason: `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`,
42
- };
56
+ reason: `process ownership could not be revalidated for PID ${member.pid}: ${observation.reason}`,
57
+ });
58
+ pendingGroups.delete(member.processGroupId);
43
59
  }
44
60
  }
61
+ if (pendingGroups.size === 0)
62
+ break;
45
63
  }
46
- return { state: "alive" };
64
+ signal?.throwIfAborted();
65
+ return observations;
47
66
  };
48
67
  /**
49
68
  * Record the live launcher and descendant lineage after run-token validation.
@@ -66,23 +85,22 @@ export const observeOwnedProcessLineage = async (ownership, host = systemProcess
66
85
  const identityFailure = launcherIdentityFailure(launcher, ownership);
67
86
  if (identityFailure !== null)
68
87
  return unavailableLineage(ownership, identityFailure);
69
- const descendants = descendantsOf(launcher.pid, processes);
88
+ const descendants = descendantsOf([launcher.pid], processes);
70
89
  const verifiedDescendants = [];
71
- for (const member of [launcher, ...descendants]) {
72
- try {
73
- if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
74
- ownership.runId)
90
+ for await (const { process: member, observation } of readProcessRunTokens(host, [launcher, ...descendants])) {
91
+ if (observation.state === "readable") {
92
+ if (observation.runId !== ownership.runId)
75
93
  return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
76
94
  if (member.pid !== launcher.pid)
77
95
  verifiedDescendants.push(member);
78
96
  }
79
- catch (cause) {
97
+ else {
80
98
  if (await processIsGone(host, member.pid)) {
81
99
  if (member.pid === launcher.pid)
82
100
  return unavailableLineage(ownership, "owned launcher exited during lineage validation");
83
101
  continue;
84
102
  }
85
- return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`);
103
+ return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${observation.reason}`);
86
104
  }
87
105
  }
88
106
  return {
@@ -251,14 +269,15 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
251
269
  }
252
270
  },
253
271
  listProcesses,
254
- async environment(pid) {
272
+ async environment(pid, signal) {
273
+ signal?.throwIfAborted();
255
274
  if (platform === "linux")
256
- return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
275
+ return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, { encoding: "utf8", signal }));
257
276
  if (platform === "darwin") {
258
- const process = (await listProcesses()).find((entry) => entry.pid === pid);
277
+ const process = (await listProcesses(signal)).find((entry) => entry.pid === pid);
259
278
  if (process === undefined)
260
279
  throw new Error(`process ${String(pid)} is not live`);
261
- const observation = (await darwinTokens?.read([process]))?.get(pid);
280
+ const observation = (await darwinTokens?.read([process], signal))?.get(pid);
262
281
  if (observation === undefined || observation.state === "unavailable")
263
282
  throw new Error(observation?.reason ?? "process run token could not be read");
264
283
  return observation.runId === undefined
@@ -267,6 +286,7 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
267
286
  }
268
287
  const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)], {
269
288
  env: hostEnvironment,
289
+ ...(signal === undefined ? {} : { signal }),
270
290
  });
271
291
  const observedEnvironment = {};
272
292
  for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
@@ -276,13 +296,16 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
276
296
  }
277
297
  return observedEnvironment;
278
298
  },
279
- async runTokens(processes) {
299
+ async runTokens(processes, signal) {
300
+ signal?.throwIfAborted();
280
301
  if (platform !== "darwin" || processes.length === 0)
281
302
  return new Map();
282
303
  try {
283
- return (await darwinTokens?.read(processes)) ?? new Map();
304
+ return (await darwinTokens?.read(processes, signal)) ?? new Map();
284
305
  }
285
306
  catch (cause) {
307
+ if (isExpectedAbort(cause, signal))
308
+ throw cause;
286
309
  void cause;
287
310
  return new Map(processes.map(({ pid }) => [
288
311
  pid,
@@ -303,17 +326,51 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
303
326
  };
304
327
  };
305
328
  export const systemProcessOwnershipHost = createSystemProcessOwnershipHost();
306
- /** Observe the current OS start identity for one live PID, when supported. */
307
- export const observeProcessStartIdentity = async (pid, host = systemProcessOwnershipHost) => {
329
+ /**
330
+ * Observe a live PID's start identity, optionally binding it to an owned run.
331
+ * Token validation is bracketed by identity reads so PID reuse cannot supply
332
+ * the first identity of a different process for an owned launch.
333
+ */
334
+ export const observeProcessStartIdentity = async (pid, host = systemProcessOwnershipHost, expectedRunId) => {
308
335
  const process = (await host.listProcesses()).find((entry) => entry.pid === pid);
309
336
  if (process === undefined || liveProcesses([process]).length === 0)
310
337
  return undefined;
311
338
  if (host.processIdentities === undefined)
312
339
  return { state: "unavailable", reason: "process identity is unsupported" };
313
- return ((await host.processIdentities([process])).get(pid) ?? {
340
+ const identity = (await host.processIdentities([process])).get(pid) ?? {
314
341
  state: "unavailable",
315
342
  reason: "process identity was not returned",
316
- });
343
+ };
344
+ if (expectedRunId === undefined || identity.state !== "readable")
345
+ return identity;
346
+ let owned = false;
347
+ for await (const { observation } of readProcessRunTokens(host, [process])) {
348
+ if (observation.state === "unavailable")
349
+ return {
350
+ state: "unavailable",
351
+ reason: `process ownership token could not be read for PID ${String(pid)}: ${observation.reason}`,
352
+ };
353
+ if (observation.runId !== expectedRunId)
354
+ return {
355
+ state: "unavailable",
356
+ reason: `process ownership token did not match the captured run for PID ${String(pid)}`,
357
+ };
358
+ owned = true;
359
+ }
360
+ if (!owned)
361
+ return {
362
+ state: "unavailable",
363
+ reason: `process ownership token was not returned for PID ${String(pid)}`,
364
+ };
365
+ const confirmed = await observeProcessStartIdentity(pid, host);
366
+ if (confirmed === undefined || confirmed.state !== "readable")
367
+ return confirmed;
368
+ return confirmed.identity === identity.identity
369
+ ? identity
370
+ : {
371
+ state: "unavailable",
372
+ reason: `process identity changed while validating the captured run token for PID ${String(pid)}`,
373
+ };
317
374
  };
318
375
  /** Revalidate a launch-time start identity immediately before signaling a PID. */
319
376
  export const signalProcessWithStartIdentity = async (pid, expectedIdentity, signal, options = {}) => {
@@ -1,7 +1,7 @@
1
1
  /** Exclude process-table entries that the operating system has already reaped. */
2
2
  export const liveProcesses = (members) => members.filter(({ state }) => !state.startsWith("Z"));
3
- /** Return every live-table descendant of a launcher in breadth-first order. */
4
- export const descendantsOf = (launcherPid, processes) => {
3
+ /** Return every live-table descendant of the selected roots in breadth-first order. */
4
+ export const descendantsOf = (rootPids, processes) => {
5
5
  const childrenByParent = new Map();
6
6
  for (const process of processes) {
7
7
  const siblings = childrenByParent.get(process.parentPid) ?? [];
@@ -9,8 +9,8 @@ export const descendantsOf = (launcherPid, processes) => {
9
9
  childrenByParent.set(process.parentPid, siblings);
10
10
  }
11
11
  const descendants = [];
12
- const pending = [...(childrenByParent.get(launcherPid) ?? [])];
13
- const visited = new Set([launcherPid]);
12
+ const pending = rootPids.flatMap((pid) => childrenByParent.get(pid) ?? []);
13
+ const visited = new Set(rootPids);
14
14
  for (const process of pending) {
15
15
  if (visited.has(process.pid))
16
16
  continue;
@@ -0,0 +1,48 @@
1
+ const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
2
+ /** Read only ownership tokens, using per-process fallback for missing batch rows. */
3
+ export async function* readProcessRunTokens(host, processes, signal) {
4
+ signal?.throwIfAborted();
5
+ if (processes.length === 0)
6
+ return;
7
+ let batch;
8
+ let batchFailure;
9
+ if (host.runTokens !== undefined) {
10
+ try {
11
+ batch =
12
+ signal === undefined
13
+ ? await host.runTokens(processes)
14
+ : await host.runTokens(processes, signal);
15
+ }
16
+ catch (cause) {
17
+ signal?.throwIfAborted();
18
+ batchFailure = errorMessage(cause);
19
+ }
20
+ }
21
+ for (const process of processes) {
22
+ signal?.throwIfAborted();
23
+ let observation = batch?.get(process.pid);
24
+ if (observation === undefined) {
25
+ try {
26
+ const environment = signal === undefined
27
+ ? await host.environment(process.pid)
28
+ : await host.environment(process.pid, signal);
29
+ observation = {
30
+ state: "readable",
31
+ runId: environment.REA_PROCESS_RUN_ID,
32
+ };
33
+ }
34
+ catch (cause) {
35
+ signal?.throwIfAborted();
36
+ const reason = errorMessage(cause);
37
+ observation = {
38
+ state: "unavailable",
39
+ reason: batchFailure === undefined
40
+ ? reason
41
+ : `${reason}; run-token batch failed: ${batchFailure}`,
42
+ };
43
+ }
44
+ }
45
+ signal?.throwIfAborted();
46
+ yield { process, observation };
47
+ }
48
+ }
@@ -0,0 +1,17 @@
1
+ /** Redact explicit transport credentials from complete and budget-cut output. */
2
+ export const redactCapturedTransportCredential = (stream, token, replacement) => {
3
+ if (token === undefined || token.length === 0)
4
+ return stream.text;
5
+ const { text } = stream;
6
+ const cutOff = stream.observedBytes > stream.bytes;
7
+ if (cutOff && !text.endsWith(token)) {
8
+ const maximumPrefixLength = Math.min(text.length, token.length - 1);
9
+ for (let prefixLength = maximumPrefixLength; prefixLength > 0; prefixLength -= 1) {
10
+ if (text.endsWith(token.slice(0, prefixLength)))
11
+ return `${text
12
+ .slice(0, text.length - prefixLength)
13
+ .replaceAll(token, replacement)}${replacement}`;
14
+ }
15
+ }
16
+ return text.replaceAll(token, replacement);
17
+ };