rea-agents 6.2.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.
- package/README.md +24 -23
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/bridge/hopper_bridge.py +2 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +59 -21
- package/dist/android/JadxSession.js +51 -9
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +85 -19
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +98 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +75 -27
- package/dist/application/DirectAnalysis.js +14 -8
- package/dist/application/DirectAnalysisCleanup.js +1 -2
- package/dist/application/DirectAnalysisStatus.js +3 -6
- package/dist/application/Doctor.js +27 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +10 -4
- package/dist/application/JsonFiles.js +16 -15
- package/dist/application/JsonInputFile.js +252 -0
- package/dist/application/LinuxHopper.js +6 -13
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +16 -3
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +103 -0
- package/dist/application/Setup.js +69 -10
- package/dist/application/SetupClientConfiguration.js +134 -23
- package/dist/application/SetupHost.js +102 -22
- package/dist/application/SetupPlan.js +18 -17
- package/dist/application/SetupSkill.js +81 -13
- package/dist/application/SupportedClients.js +305 -37
- package/dist/application/Uninstall.js +172 -8
- package/dist/application/UpdateMaintenance.js +23 -23
- package/dist/application/Utf8JsonInput.js +71 -0
- package/dist/application/WebScriptExportService.js +130 -57
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/android/AndroidAnalysisService.js +1 -1
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +18 -1
- package/dist/application/binary/BinarySessionOpen.js +9 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +20 -3
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +23 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -36
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +74 -36
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +53 -42
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +293 -238
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +120 -28
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +10 -20
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +11 -5
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +206 -66
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +18 -23
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +5 -2
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +6 -4
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +29 -15
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeCallRoutes.js +2 -4
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +34 -31
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +218 -80
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +179 -87
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +76 -49
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +134 -92
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +116 -50
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +87 -25
- package/dist/artifacts/inventory/hashStableRootArtifact.js +70 -0
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +73 -30
- package/dist/artifacts/inventory/scanReader.js +43 -20
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +72 -28
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +9 -3
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +48 -23
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +63 -7
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +208 -43
- package/dist/browser/PlaywrightScenarioSession.js +130 -65
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +35 -9
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +12 -13
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +14 -10
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -13
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +12 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +68 -22
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +11 -2
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +7 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +14 -7
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactComparisonExample.js +5 -5
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +104 -13
- package/dist/contracts/javascript/electronToolContracts.js +16 -3
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +5 -4
- package/dist/contracts/sessionToolSchemas.js +9 -4
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +7 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -4
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +5 -2
- package/dist/domain/analysisView/analysisView.js +53 -5
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/android/androidPartialObservation.js +36 -0
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +3 -3
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +39 -11
- package/dist/domain/artifactGraph.js +6 -4
- package/dist/domain/artifactIdentity.js +37 -9
- package/dist/domain/artifactInspection.js +10 -50
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +16 -17
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +12 -6
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +14 -15
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +20 -21
- package/dist/domain/javascript/electronStaticAnalysisNative.js +73 -41
- package/dist/domain/javascript/electronStaticAnalysisValues.js +24 -4
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +6 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +18 -14
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +91 -28
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +72 -45
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +16 -8
- package/dist/domain/javascript/javascriptAstFingerprint.js +60 -33
- package/dist/domain/javascript/javascriptAstValues.js +54 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +12 -7
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +15 -17
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +379 -30
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +43 -42
- package/dist/domain/javascript/javascriptSemanticGraph.js +205 -52
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +21 -11
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +139 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +774 -136
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +98 -41
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +9 -7
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +72 -28
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +100 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +33 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +4 -5
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +34 -48
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +25 -2
- package/dist/domain/javascript/javascriptSemanticValues.js +169 -30
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +13 -12
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +69 -31
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +47 -6
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +94 -59
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +102 -11
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +67 -0
- package/dist/domain/process/processCaptureValidation.js +83 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +62 -10
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +32 -23
- package/dist/domain/referenceSourceImportParsing.js +40 -48
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +23 -3
- package/dist/domain/webCaptureDiff.js +170 -30
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +5 -4
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +65 -31
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +73 -0
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +90 -8
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +123 -58
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperCleanup.js +1 -1
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +10 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +7 -3
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +100 -20
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +104 -51
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +116 -22
- package/dist/process/capture/ProcessCaptureLifecycle.js +363 -86
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +202 -47
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/analysisAdmission.js +8 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +118 -47
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +6 -7
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/helpers.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerArtifactTools.js +2 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +36 -5
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedTools.js +7 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerOfficialTools.js +31 -25
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +58 -21
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +38 -7
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +31 -1
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -7,12 +7,14 @@ export class OwnedCommandFailure extends Error {
|
|
|
7
7
|
snapshot;
|
|
8
8
|
cleanupFailure;
|
|
9
9
|
resources;
|
|
10
|
-
|
|
10
|
+
cleanupOwner;
|
|
11
|
+
constructor(reason, message, snapshot = null, cleanupFailure = null, options, resources = [], cleanupOwner) {
|
|
11
12
|
super(message, options);
|
|
12
13
|
this.reason = reason;
|
|
13
14
|
this.snapshot = snapshot;
|
|
14
15
|
this.cleanupFailure = cleanupFailure;
|
|
15
16
|
this.resources = resources;
|
|
17
|
+
this.cleanupOwner = cleanupOwner;
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
/** Execute a single owned process with independent cleanup and bounded diagnostic retention. */
|
|
@@ -102,14 +104,13 @@ const collectOwnedCommand = async (spawn, limits, launcher, deadline, callerSign
|
|
|
102
104
|
}
|
|
103
105
|
const stopped = await supervisor.stop();
|
|
104
106
|
const snapshot = supervisor.snapshot();
|
|
105
|
-
supervisor.dispose();
|
|
106
107
|
if (stopped.status === "incomplete")
|
|
107
108
|
throw new OwnedCommandFailure(failure?.reason ?? "process", failure?.message ?? "Command cleanup failed.", snapshot, stopped.reason, failure === undefined ? undefined : { cause: failure }, [
|
|
108
109
|
spawn.runId,
|
|
109
110
|
...(spawn.cwd === undefined ? [] : [spawn.cwd]),
|
|
110
111
|
`pid:${launched.ownership.leaderPid}`,
|
|
111
112
|
`process-group:${launched.ownership.processGroupId}`,
|
|
112
|
-
]);
|
|
113
|
+
], supervisor);
|
|
113
114
|
if (failure !== undefined)
|
|
114
115
|
throw new OwnedCommandFailure(failure.reason, failure.message, snapshot, failure.cleanupFailure, { cause: failure }, failure.resources);
|
|
115
116
|
if (callerSignal?.aborted)
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
-
|
|
463
|
-
|
|
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
|
-
|
|
477
|
-
unreadable.push({ process, diagnostic:
|
|
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
|
-
|
|
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
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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(
|
|
612
|
+
recordOwned(process);
|
|
601
613
|
continue;
|
|
602
614
|
}
|
|
603
615
|
stillUnreadable.push({
|
|
604
|
-
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,49 +4,74 @@ 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
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
+
const groupIds = [...new Set(processGroupIds)];
|
|
12
|
+
if (groupIds.length === 0)
|
|
13
|
+
return new Map();
|
|
14
|
+
let processes;
|
|
11
15
|
try {
|
|
12
|
-
|
|
16
|
+
processes = liveProcesses(await host.listProcesses(signal));
|
|
13
17
|
}
|
|
14
18
|
catch (cause) {
|
|
15
19
|
signal?.throwIfAborted();
|
|
16
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
50
|
+
else {
|
|
51
|
+
const gone = await processIsGone(host, member.pid);
|
|
37
52
|
signal?.throwIfAborted();
|
|
38
|
-
if (!
|
|
39
|
-
|
|
53
|
+
if (!gone) {
|
|
54
|
+
observations.set(member.processGroupId, {
|
|
40
55
|
state: "unverifiable",
|
|
41
|
-
reason: `process ownership could not be revalidated for PID ${member.pid}: ${
|
|
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
|
-
|
|
64
|
+
signal?.throwIfAborted();
|
|
65
|
+
return observations;
|
|
47
66
|
};
|
|
48
|
-
/**
|
|
49
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Record the live launcher and descendant lineage after run-token validation.
|
|
69
|
+
*
|
|
70
|
+
* The observation is intentionally point-in-time. A verified empty descendant
|
|
71
|
+
* list means no descendants were live during this observation, not that the
|
|
72
|
+
* run never created a short-lived child.
|
|
73
|
+
*/
|
|
74
|
+
export const observeOwnedProcessLineage = async (ownership, host = systemProcessOwnershipHost) => {
|
|
50
75
|
let processes;
|
|
51
76
|
try {
|
|
52
77
|
processes = liveProcesses(await host.listProcesses());
|
|
@@ -60,23 +85,22 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
|
|
|
60
85
|
const identityFailure = launcherIdentityFailure(launcher, ownership);
|
|
61
86
|
if (identityFailure !== null)
|
|
62
87
|
return unavailableLineage(ownership, identityFailure);
|
|
63
|
-
const descendants = descendantsOf(launcher.pid, processes);
|
|
88
|
+
const descendants = descendantsOf([launcher.pid], processes);
|
|
64
89
|
const verifiedDescendants = [];
|
|
65
|
-
for (const member of [launcher, ...descendants]) {
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
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)
|
|
69
93
|
return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
|
|
70
94
|
if (member.pid !== launcher.pid)
|
|
71
95
|
verifiedDescendants.push(member);
|
|
72
96
|
}
|
|
73
|
-
|
|
97
|
+
else {
|
|
74
98
|
if (await processIsGone(host, member.pid)) {
|
|
75
99
|
if (member.pid === launcher.pid)
|
|
76
100
|
return unavailableLineage(ownership, "owned launcher exited during lineage validation");
|
|
77
101
|
continue;
|
|
78
102
|
}
|
|
79
|
-
return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${
|
|
103
|
+
return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${observation.reason}`);
|
|
80
104
|
}
|
|
81
105
|
}
|
|
82
106
|
return {
|
|
@@ -245,14 +269,15 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
245
269
|
}
|
|
246
270
|
},
|
|
247
271
|
listProcesses,
|
|
248
|
-
async environment(pid) {
|
|
272
|
+
async environment(pid, signal) {
|
|
273
|
+
signal?.throwIfAborted();
|
|
249
274
|
if (platform === "linux")
|
|
250
|
-
return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
|
|
275
|
+
return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, { encoding: "utf8", signal }));
|
|
251
276
|
if (platform === "darwin") {
|
|
252
|
-
const process = (await listProcesses()).find((entry) => entry.pid === pid);
|
|
277
|
+
const process = (await listProcesses(signal)).find((entry) => entry.pid === pid);
|
|
253
278
|
if (process === undefined)
|
|
254
279
|
throw new Error(`process ${String(pid)} is not live`);
|
|
255
|
-
const observation = (await darwinTokens?.read([process]))?.get(pid);
|
|
280
|
+
const observation = (await darwinTokens?.read([process], signal))?.get(pid);
|
|
256
281
|
if (observation === undefined || observation.state === "unavailable")
|
|
257
282
|
throw new Error(observation?.reason ?? "process run token could not be read");
|
|
258
283
|
return observation.runId === undefined
|
|
@@ -261,6 +286,7 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
261
286
|
}
|
|
262
287
|
const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)], {
|
|
263
288
|
env: hostEnvironment,
|
|
289
|
+
...(signal === undefined ? {} : { signal }),
|
|
264
290
|
});
|
|
265
291
|
const observedEnvironment = {};
|
|
266
292
|
for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
|
|
@@ -270,13 +296,16 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
270
296
|
}
|
|
271
297
|
return observedEnvironment;
|
|
272
298
|
},
|
|
273
|
-
async runTokens(processes) {
|
|
299
|
+
async runTokens(processes, signal) {
|
|
300
|
+
signal?.throwIfAborted();
|
|
274
301
|
if (platform !== "darwin" || processes.length === 0)
|
|
275
302
|
return new Map();
|
|
276
303
|
try {
|
|
277
|
-
return (await darwinTokens?.read(processes)) ?? new Map();
|
|
304
|
+
return (await darwinTokens?.read(processes, signal)) ?? new Map();
|
|
278
305
|
}
|
|
279
306
|
catch (cause) {
|
|
307
|
+
if (isExpectedAbort(cause, signal))
|
|
308
|
+
throw cause;
|
|
280
309
|
void cause;
|
|
281
310
|
return new Map(processes.map(({ pid }) => [
|
|
282
311
|
pid,
|
|
@@ -297,17 +326,51 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
297
326
|
};
|
|
298
327
|
};
|
|
299
328
|
export const systemProcessOwnershipHost = createSystemProcessOwnershipHost();
|
|
300
|
-
/**
|
|
301
|
-
|
|
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) => {
|
|
302
335
|
const process = (await host.listProcesses()).find((entry) => entry.pid === pid);
|
|
303
336
|
if (process === undefined || liveProcesses([process]).length === 0)
|
|
304
337
|
return undefined;
|
|
305
338
|
if (host.processIdentities === undefined)
|
|
306
339
|
return { state: "unavailable", reason: "process identity is unsupported" };
|
|
307
|
-
|
|
340
|
+
const identity = (await host.processIdentities([process])).get(pid) ?? {
|
|
308
341
|
state: "unavailable",
|
|
309
342
|
reason: "process identity was not returned",
|
|
310
|
-
}
|
|
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
|
+
};
|
|
311
374
|
};
|
|
312
375
|
/** Revalidate a launch-time start identity immediately before signaling a PID. */
|
|
313
376
|
export const signalProcessWithStartIdentity = async (pid, expectedIdentity, signal, options = {}) => {
|
|
@@ -331,16 +394,6 @@ export const signalProcessWithStartIdentity = async (pid, expectedIdentity, sign
|
|
|
331
394
|
export const prepareProcessOwnershipInspection = async (signal) => {
|
|
332
395
|
await systemProcessOwnershipHost.prepare?.(signal);
|
|
333
396
|
};
|
|
334
|
-
/** Observe one group without signaling it, failing closed on identity doubt. */
|
|
335
|
-
export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost, signal) => observeOwnedProcessGroupWithHost(ownership, host, signal);
|
|
336
|
-
/**
|
|
337
|
-
* Record the live launcher and descendant lineage after run-token validation.
|
|
338
|
-
*
|
|
339
|
-
* The observation is intentionally point-in-time. A verified empty descendant
|
|
340
|
-
* list means no descendants were live during this observation, not that the
|
|
341
|
-
* run never created a short-lived child.
|
|
342
|
-
*/
|
|
343
|
-
export const observeOwnedProcessLineage = async (ownership, host = systemProcessOwnershipHost) => observeOwnedProcessLineageWithHost(ownership, host);
|
|
344
397
|
const processIsGone = async (host, pid) => {
|
|
345
398
|
try {
|
|
346
399
|
return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
|
|
@@ -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
|
|
4
|
-
export const descendantsOf = (
|
|
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 =
|
|
13
|
-
const visited = new Set(
|
|
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;
|