rea-agents 5.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -655
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +208 -0
- package/bridge/native/rea_lldb_tracer.py +839 -0
- package/bridge/process/ProcessRunTokenReader.swift +297 -0
- package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
- package/bridge/pwndbg/core_context.py +101 -0
- package/bridge/pwndbg/launch.py +39 -0
- package/bridge/pwndbg/launch_impl.py +34 -0
- package/bridge/pwntools/decoder_runtime.py +59 -0
- package/bridge/pwntools/layout.py +39 -0
- package/bridge/pwntools/layout_impl.py +309 -0
- package/bridge/pwntools/recorded_crash.py +39 -0
- package/bridge/pwntools/recorded_crash_impl.py +147 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +20 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +27 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +97 -33
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +24 -12
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +134 -0
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
- package/dist/application/binary/BinarySession.js +131 -76
- package/dist/application/binary/BinarySessionOpen.js +19 -6
- package/dist/application/binary/BinarySessionRecords.js +45 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +64 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +42 -5
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
- package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
- package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
- package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +165 -12
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +34 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +137 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +17 -0
- package/dist/browser/history/HarCapture.js +165 -0
- package/dist/browser/history/HarCaptureAdapter.js +20 -0
- package/dist/browser/history/HarCaptureProcess.js +57 -0
- package/dist/browser/history/HarJson.js +92 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +26 -1
- package/dist/cli/binaryDiagnosticsCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +78 -20
- package/dist/cli/electronCommands.js +21 -13
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +20 -3
- package/dist/cli/jsonOutput.js +38 -0
- package/dist/cli/nativeCallCommands.js +34 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/streamedJsonOutput.js +56 -0
- package/dist/cli/utilityCommands.js +2 -0
- package/dist/cli/webNetworkCaptureCommands.js +40 -0
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +11 -4
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -1
- package/dist/cliJsonInput.js +35 -1
- package/dist/cliOutput.js +21 -6
- package/dist/composition/binaryDiagnostics.js +8 -0
- package/dist/composition/evm.js +4 -0
- package/dist/composition/webNetworkCaptures.js +6 -0
- package/dist/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +8 -6
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +21 -3
- package/dist/contracts/officialToolContracts.js +26 -24
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +18 -5
- package/dist/contracts/sessionStatusContract.js +8 -2
- package/dist/contracts/sessionToolContracts.js +8 -3
- package/dist/contracts/sessionToolSchemas.js +8 -4
- package/dist/contracts/toolContractExamples.js +1 -2
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -1
- package/dist/contracts/toolOutputSchemaGroups.js +33 -28
- package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +22 -2
- package/dist/domain/analysisErrorCore.js +61 -5
- package/dist/domain/analysisErrorPresentation.js +95 -12
- package/dist/domain/analysisErrorProjection.js +148 -19
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +478 -0
- package/dist/domain/apple/dylibResolutionFindings.js +77 -0
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +5 -2
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +78 -11
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +108 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +10 -4
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +37 -6
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +91 -3
- package/dist/domain/localPath.js +8 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +186 -0
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/objcSwiftMetadata.js +0 -39
- package/dist/domain/native/recordedCrash.js +266 -0
- package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
- package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
- package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
- package/dist/domain/process/processCaptureParsing.js +54 -0
- package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
- package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +3 -3
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +9 -46
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
- package/dist/dotnet/ManagedMemberInspector.js +4 -2
- package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
- package/dist/dotnet/ManagedMemberRows.js +14 -3
- package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
- package/dist/dotnet/ManagedMetadataInventory.js +38 -28
- package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
- package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
- package/dist/dotnet/ManagedPeReader.js +11 -0
- package/dist/evm/EvmBytecodeCarrier.js +21 -0
- package/dist/evm/EvmWorkerLimits.js +40 -0
- package/dist/evm/EvmoleFailures.js +126 -0
- package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
- package/dist/evm/EvmoleInterfaceProvider.js +273 -0
- package/dist/evm/EvmoleInterfaceWorker.js +87 -0
- package/dist/evm/EvmoleRelease.js +16 -0
- package/dist/firmware/FirmwareCommand.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +34 -16
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +33 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +82 -84
- package/dist/native/LldbCallTracer.js +541 -0
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +194 -0
- package/dist/native/NativeMacOSProvider.js +117 -20
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
- package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
- package/dist/native/pwntools/PwntoolsFailures.js +180 -0
- package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
- package/dist/native/pwntools/PwntoolsRelease.js +19 -0
- package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
- package/dist/process/DarwinProcessRunTokenReader.js +293 -0
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +118 -0
- package/dist/process/ProcessOwnership.js +431 -51
- package/dist/process/ProcessOwnershipObservation.js +209 -27
- package/dist/process/ProviderProcess.js +68 -10
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +37 -8
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +3 -5
- package/dist/server/registerEvmTools.js +15 -0
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +72 -46
- package/dist/server/registerRecordedCrashTools.js +15 -0
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +13 -5
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +26 -0
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +3 -1
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +63 -11
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +42 -9
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +32 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
- package/third_party/README.md +60 -0
- package/third_party/evmole/LICENSE +21 -0
- package/third_party/evmole/README.md +22 -0
- package/third_party/pwndbg/LICENSE.md +21 -0
- package/third_party/pwndbg/README.md +23 -0
- package/third_party/pwntools/README.md +40 -0
- package/dist/application/AuthorizedArtifactInventory.js +0 -7
- package/dist/application/ProcessCaptureLifecycle.js +0 -299
- package/dist/application/StoreFileLock.js +0 -124
- package/dist/contracts/processCaptureExample.js +0 -2
- package/dist/domain/bytecodeProvider.js +0 -178
- package/dist/domain/customProtocolCapture.js +0 -137
- package/dist/domain/eventProcessTree.js +0 -225
- package/dist/domain/mobileApplicationInvestigation.js +0 -159
- package/dist/domain/packageAnalysis.js +0 -123
- package/dist/domain/peInspection.js +0 -197
- package/dist/domain/processCaptureParsing.js +0 -21
- package/dist/domain/protocolCapture.js +0 -217
- package/dist/domain/runtimeIdentification.js +0 -212
- package/dist/generatedMcpToolCatalog.js +0 -37
- package/dist/ghidra/GhidraDefaults.js +0 -2
- /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
- /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
- /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
- /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
- /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
- /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
- /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
- /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
- /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
- /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
- /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
|
-
import {
|
|
3
|
+
import { errorMessage, systemProcessOwnershipHost as systemHost, } from "./ProcessOwnershipObservation.js";
|
|
4
4
|
import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
|
|
5
5
|
import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
|
|
6
6
|
const execFileAsync = promisify(execFile);
|
|
@@ -28,7 +28,6 @@ export const cleanupWindowsProcessTree = async (rootPid, host = systemWindowsPro
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
-
const systemHost = createSystemProcessOwnershipHost();
|
|
32
31
|
const systemWindowsProcessTreeHost = {
|
|
33
32
|
async terminateTree(rootPid) {
|
|
34
33
|
try {
|
|
@@ -59,7 +58,7 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
|
|
|
59
58
|
return plan;
|
|
60
59
|
let signaled = false;
|
|
61
60
|
for (const processGroupId of plan.signalOrder) {
|
|
62
|
-
const revalidation = await revalidateOwnedProcessGroup(processGroupId, ownership, host);
|
|
61
|
+
const revalidation = await revalidateOwnedProcessGroup(processGroupId, ownership, host, plan.tokenOwnedIdentities);
|
|
63
62
|
if ("cleaned" in revalidation)
|
|
64
63
|
return revalidation;
|
|
65
64
|
if (revalidation.empty)
|
|
@@ -77,22 +76,36 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
|
|
|
77
76
|
};
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
|
-
|
|
79
|
+
if (plan.unresolved.length > 0)
|
|
80
|
+
return cleanupValidationFailure(plan.unresolved, plan.unverified);
|
|
81
|
+
return {
|
|
82
|
+
cleaned: true,
|
|
83
|
+
signaled,
|
|
84
|
+
...(plan.unverified.length === 0 ? {} : { unverified: plan.unverified }),
|
|
85
|
+
};
|
|
81
86
|
};
|
|
82
87
|
/** Verify that no live process still carries an owned capture run token. */
|
|
83
|
-
export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost) => {
|
|
88
|
+
export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost, captureBaseline, relation) => {
|
|
84
89
|
const processTable = await readLiveProcessTable(host);
|
|
85
90
|
if (!processTable.available)
|
|
86
91
|
return {
|
|
87
92
|
cleaned: false,
|
|
88
93
|
reason: `process table could not be inspected: ${processTable.reason}`,
|
|
89
94
|
};
|
|
90
|
-
const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host);
|
|
95
|
+
const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host, captureBaseline, relation);
|
|
91
96
|
if (scan.failures.length > 0)
|
|
92
|
-
return cleanupValidationFailure(scan.failures);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
return cleanupValidationFailure(scan.failures, scan.unverified);
|
|
98
|
+
if (scan.owned.length > 0)
|
|
99
|
+
return {
|
|
100
|
+
cleaned: false,
|
|
101
|
+
reason: "token-owned process remained after cleanup",
|
|
102
|
+
...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
cleaned: true,
|
|
106
|
+
signaled: false,
|
|
107
|
+
...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
|
|
108
|
+
};
|
|
96
109
|
};
|
|
97
110
|
const readLiveProcessTable = async (host) => {
|
|
98
111
|
try {
|
|
@@ -106,18 +119,37 @@ const readLiveProcessTable = async (host) => {
|
|
|
106
119
|
}
|
|
107
120
|
};
|
|
108
121
|
const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
122
|
+
const sampledProcessGroupIds = new Set((ownership.sampledProcessGroupIds ?? []).filter((processGroupId) => Number.isSafeInteger(processGroupId) && processGroupId > 0));
|
|
109
123
|
const tokenOwned = ownership.sweepTokenOwnedProcesses === true
|
|
110
|
-
? await scanTokenOwnedProcesses(processes, ownership.runId, host
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline, {
|
|
125
|
+
leaderPid: ownership.leaderPid,
|
|
126
|
+
processGroupId: ownership.processGroupId,
|
|
127
|
+
...(sampledProcessGroupIds.size === 0
|
|
128
|
+
? {}
|
|
129
|
+
: { sampledProcessGroupIds: [...sampledProcessGroupIds] }),
|
|
130
|
+
})
|
|
131
|
+
: { owned: [], failures: [], unverified: [], identities: new Map() };
|
|
114
132
|
const tokenOwnedGroupIds = new Set(tokenOwned.owned.map(({ processGroupId }) => processGroupId));
|
|
115
133
|
const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
|
|
116
134
|
const rootMembers = processes.filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
117
135
|
if (launcher === undefined &&
|
|
118
136
|
rootMembers.length === 0 &&
|
|
119
|
-
tokenOwned.owned.length === 0
|
|
120
|
-
|
|
137
|
+
tokenOwned.owned.length === 0 &&
|
|
138
|
+
!processes.some(({ processGroupId }) => sampledProcessGroupIds.has(processGroupId)))
|
|
139
|
+
return tokenOwned.failures.length > 0
|
|
140
|
+
? {
|
|
141
|
+
signalOrder: [],
|
|
142
|
+
tokenOwnedIdentities: tokenOwned.identities,
|
|
143
|
+
unresolved: tokenOwned.failures,
|
|
144
|
+
unverified: tokenOwned.unverified,
|
|
145
|
+
}
|
|
146
|
+
: {
|
|
147
|
+
cleaned: true,
|
|
148
|
+
signaled: false,
|
|
149
|
+
...(tokenOwned.unverified.length === 0
|
|
150
|
+
? {}
|
|
151
|
+
: { unverified: tokenOwned.unverified }),
|
|
152
|
+
};
|
|
121
153
|
let descendants = [];
|
|
122
154
|
if (launcher !== undefined) {
|
|
123
155
|
const identityFailure = launcherIdentityFailure(launcher, ownership);
|
|
@@ -131,28 +163,62 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
131
163
|
processGroupIds.add(descendant.processGroupId);
|
|
132
164
|
for (const process of tokenOwned.owned)
|
|
133
165
|
processGroupIds.add(process.processGroupId);
|
|
166
|
+
for (const processGroupId of sampledProcessGroupIds)
|
|
167
|
+
processGroupIds.add(processGroupId);
|
|
168
|
+
const signalableGroups = new Set();
|
|
169
|
+
const unresolved = [...tokenOwned.failures];
|
|
170
|
+
const unverifiableSampledGroups = new Set();
|
|
134
171
|
for (const processGroupId of processGroupIds) {
|
|
135
172
|
if (processGroupId === ownership.processGroupId)
|
|
136
173
|
continue;
|
|
137
174
|
const groupLeader = processes.find(({ pid, processGroupId: observedGroupId }) => pid === processGroupId && observedGroupId === processGroupId);
|
|
138
175
|
if ((groupLeader === undefined || !descendantPids.has(groupLeader.pid)) &&
|
|
139
|
-
!tokenOwnedGroupIds.has(processGroupId)
|
|
176
|
+
!tokenOwnedGroupIds.has(processGroupId) &&
|
|
177
|
+
!sampledProcessGroupIds.has(processGroupId))
|
|
140
178
|
return {
|
|
141
179
|
cleaned: false,
|
|
142
180
|
reason: "descendant process-group leader identity could not be verified",
|
|
143
181
|
};
|
|
182
|
+
if ((groupLeader === undefined || !descendantPids.has(groupLeader.pid)) &&
|
|
183
|
+
!tokenOwnedGroupIds.has(processGroupId))
|
|
184
|
+
unverifiableSampledGroups.add(processGroupId);
|
|
144
185
|
}
|
|
145
186
|
const liveMembers = processes.filter(({ processGroupId }) => processGroupIds.has(processGroupId));
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
187
|
+
for (const processGroupId of processGroupIds) {
|
|
188
|
+
const members = liveMembers.filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
|
|
189
|
+
if (members.length === 0)
|
|
190
|
+
continue;
|
|
191
|
+
const failures = await processOwnershipFailures(members, ownership.runId, host, tokenOwned.identities);
|
|
192
|
+
if (failures.length === 0 && unverifiableSampledGroups.has(processGroupId))
|
|
193
|
+
unresolved.push(...members.map(({ pid }) => ({
|
|
194
|
+
pid,
|
|
195
|
+
reason: "process-identity-unavailable",
|
|
196
|
+
diagnostic: "sampled process-group leader identity could not be verified",
|
|
197
|
+
})));
|
|
198
|
+
const scanFailures = tokenOwned.failures.filter(({ pid }) => members.some((member) => member.pid === pid));
|
|
199
|
+
if (failures.length > 0)
|
|
200
|
+
unresolved.push(...failures);
|
|
201
|
+
if (failures.length === 0 &&
|
|
202
|
+
scanFailures.length === 0 &&
|
|
203
|
+
!unverifiableSampledGroups.has(processGroupId))
|
|
204
|
+
signalableGroups.add(processGroupId);
|
|
205
|
+
}
|
|
206
|
+
if (ownership.sweepTokenOwnedProcesses !== true && unresolved.length > 0)
|
|
207
|
+
return cleanupValidationFailure(unresolved, tokenOwned.unverified);
|
|
149
208
|
return {
|
|
150
|
-
signalOrder: [
|
|
151
|
-
.filter((
|
|
152
|
-
.sort((left, right) => left
|
|
209
|
+
signalOrder: [...signalableGroups]
|
|
210
|
+
.filter((groupId) => processGroupIds.has(groupId))
|
|
211
|
+
.sort((left, right) => left === ownership.processGroupId
|
|
212
|
+
? -1
|
|
213
|
+
: right === ownership.processGroupId
|
|
214
|
+
? 1
|
|
215
|
+
: left - right),
|
|
216
|
+
tokenOwnedIdentities: tokenOwned.identities,
|
|
217
|
+
unresolved,
|
|
218
|
+
unverified: tokenOwned.unverified,
|
|
153
219
|
};
|
|
154
220
|
};
|
|
155
|
-
const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
|
|
221
|
+
const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expectedIdentities) => {
|
|
156
222
|
let members;
|
|
157
223
|
try {
|
|
158
224
|
members = liveProcesses(await host.listProcesses()).filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
|
|
@@ -163,7 +229,7 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
|
|
|
163
229
|
reason: `process ownership could not be revalidated: ${errorMessage(cause)}`,
|
|
164
230
|
};
|
|
165
231
|
}
|
|
166
|
-
const failures = await processOwnershipFailures(members, ownership.runId, host);
|
|
232
|
+
const failures = await processOwnershipFailures(members, ownership.runId, host, expectedIdentities);
|
|
167
233
|
if (failures.length > 0)
|
|
168
234
|
return cleanupValidationFailure(failures);
|
|
169
235
|
if (processGroupId === ownership.processGroupId) {
|
|
@@ -184,15 +250,103 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
|
|
|
184
250
|
};
|
|
185
251
|
return { empty: members.length === 0 };
|
|
186
252
|
};
|
|
187
|
-
const cleanupValidationFailure = (failures) =>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
253
|
+
const cleanupValidationFailure = (failures, unverified = []) => {
|
|
254
|
+
const unverifiedEntry = unverified.length === 0 ? {} : { unverified };
|
|
255
|
+
const unreadable = failures.filter(({ reason }) => reason === "environment-unreadable");
|
|
256
|
+
if (failures.some(({ reason }) => reason === "run-token-mismatch"))
|
|
257
|
+
return {
|
|
258
|
+
cleaned: false,
|
|
259
|
+
reason: "process tree contains an unowned or PID-reused process",
|
|
260
|
+
failures,
|
|
261
|
+
...unverifiedEntry,
|
|
262
|
+
};
|
|
263
|
+
if (failures.some(({ reason }) => reason === "process-identity-unavailable"))
|
|
264
|
+
return {
|
|
265
|
+
cleaned: false,
|
|
266
|
+
reason: "process identity could not be revalidated",
|
|
267
|
+
failures,
|
|
268
|
+
...unverifiedEntry,
|
|
269
|
+
};
|
|
270
|
+
if (unreadable.length > 0) {
|
|
271
|
+
const counts = new Map();
|
|
272
|
+
for (const { diagnostic } of unreadable) {
|
|
273
|
+
const category = sanitizedTokenReadFailure(diagnostic);
|
|
274
|
+
counts.set(category, (counts.get(category) ?? 0) + 1);
|
|
275
|
+
}
|
|
276
|
+
const breakdown = [...counts]
|
|
277
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
278
|
+
.map(([category, count]) => `${category}=${String(count)}`)
|
|
279
|
+
.join(", ");
|
|
280
|
+
const candidates = unreadable
|
|
281
|
+
.map(({ pid, diagnostic }) => `${String(pid)}=${sanitizedTokenReadFailure(diagnostic)}`)
|
|
282
|
+
.sort((left, right) => left.localeCompare(right));
|
|
283
|
+
return {
|
|
284
|
+
cleaned: false,
|
|
285
|
+
reason: `process ownership token could not be read for ${String(unreadable.length)} live process(es): ${breakdown}; live candidates ${candidates.join(", ")}`,
|
|
286
|
+
failures,
|
|
287
|
+
...unverifiedEntry,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
cleaned: false,
|
|
292
|
+
reason: "process ownership could not be revalidated",
|
|
293
|
+
failures,
|
|
294
|
+
...unverifiedEntry,
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
const sanitizedTokenReadFailure = (diagnostic) => {
|
|
298
|
+
if (diagnostic === "environment_unavailable")
|
|
299
|
+
return diagnostic;
|
|
300
|
+
if (diagnostic === "platform_binary_environment_withheld")
|
|
301
|
+
return diagnostic;
|
|
302
|
+
const environmentErrno = /^(EACCES|EPERM|ENOENT|ESRCH):/u.exec(diagnostic ?? "");
|
|
303
|
+
if (environmentErrno?.[1] !== undefined)
|
|
304
|
+
return `environment_errno_${environmentErrno[1]}`;
|
|
305
|
+
if (diagnostic === "apple_vector_unavailable")
|
|
306
|
+
return diagnostic;
|
|
307
|
+
if (diagnostic === "ambiguous_environment_boundary")
|
|
308
|
+
return diagnostic;
|
|
309
|
+
if (diagnostic === "malformed_procargs")
|
|
310
|
+
return diagnostic;
|
|
311
|
+
if (diagnostic === "process_identity_changed_during_token_read")
|
|
312
|
+
return diagnostic;
|
|
313
|
+
if (diagnostic === "process_not_in_snapshot")
|
|
314
|
+
return diagnostic;
|
|
315
|
+
const processTableFailure = /^process_table_failed_(\d+)$/u.exec(diagnostic ?? "");
|
|
316
|
+
if (processTableFailure?.[1] !== undefined)
|
|
317
|
+
return `process_table_errno_${processTableFailure[1]}`;
|
|
318
|
+
const sysctlFailure = /^sysctl_failed_(\d+)$/u.exec(diagnostic ?? "");
|
|
319
|
+
if (sysctlFailure?.[1] !== undefined)
|
|
320
|
+
return `sysctl_errno_${sysctlFailure[1]}`;
|
|
321
|
+
if (diagnostic === "reader_failure")
|
|
322
|
+
return diagnostic;
|
|
323
|
+
if (diagnostic === "duplicate_run_token")
|
|
324
|
+
return diagnostic;
|
|
325
|
+
if (diagnostic === "invalid_run_token_encoding")
|
|
326
|
+
return diagnostic;
|
|
327
|
+
return "other_unavailable";
|
|
328
|
+
};
|
|
329
|
+
const processOwnershipFailures = async (members, runId, host, expectedIdentities = new Map()) => {
|
|
195
330
|
const failures = [];
|
|
331
|
+
if (expectedIdentities.size > 0 && host.processIdentities !== undefined) {
|
|
332
|
+
const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
|
|
333
|
+
const observed = await host.processIdentities(expectedMembers);
|
|
334
|
+
for (const member of expectedMembers) {
|
|
335
|
+
const expected = expectedIdentities.get(member.pid);
|
|
336
|
+
const current = observed.get(member.pid);
|
|
337
|
+
if (expected === null ||
|
|
338
|
+
current?.state !== "readable" ||
|
|
339
|
+
current.identity !== expected) {
|
|
340
|
+
if (await processIsGone(host, member.pid))
|
|
341
|
+
continue;
|
|
342
|
+
failures.push({
|
|
343
|
+
pid: member.pid,
|
|
344
|
+
reason: "process-identity-unavailable",
|
|
345
|
+
diagnostic: "process identity changed or became unavailable before signal",
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
196
350
|
for (const member of members) {
|
|
197
351
|
try {
|
|
198
352
|
if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !== runId)
|
|
@@ -219,36 +373,262 @@ const processOwnershipFailures = async (members, runId, host) => {
|
|
|
219
373
|
});
|
|
220
374
|
}
|
|
221
375
|
}
|
|
376
|
+
if (failures.length === 0 &&
|
|
377
|
+
expectedIdentities.size > 0 &&
|
|
378
|
+
host.processIdentities !== undefined) {
|
|
379
|
+
const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
|
|
380
|
+
const observed = await host.processIdentities(expectedMembers);
|
|
381
|
+
for (const member of expectedMembers) {
|
|
382
|
+
const expected = expectedIdentities.get(member.pid);
|
|
383
|
+
const current = observed.get(member.pid);
|
|
384
|
+
if (expected !== null &&
|
|
385
|
+
current?.state === "readable" &&
|
|
386
|
+
current.identity === expected)
|
|
387
|
+
continue;
|
|
388
|
+
if (await processIsGone(host, member.pid))
|
|
389
|
+
continue;
|
|
390
|
+
failures.push({
|
|
391
|
+
pid: member.pid,
|
|
392
|
+
reason: "process-identity-unavailable",
|
|
393
|
+
diagnostic: "process identity changed or became unavailable during token validation",
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
222
397
|
return failures;
|
|
223
398
|
};
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
399
|
+
const TOKEN_READ_RETRY_ATTEMPTS = 3;
|
|
400
|
+
const TOKEN_READ_RETRY_DELAY_MS = 40;
|
|
401
|
+
/** Darwin reports this when the kernel withholds a platform binary's environment. */
|
|
402
|
+
const PLATFORM_BINARY_ENVIRONMENT_WITHHELD = "platform_binary_environment_withheld";
|
|
403
|
+
const currentProcessUid = () => typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
404
|
+
/**
|
|
405
|
+
* Whether the operating system provably withheld this candidate's run token:
|
|
406
|
+
* current macOS omits the environment of Apple platform binaries from
|
|
407
|
+
* KERN_PROCARGS2 and fails with EINVAL for processes owned by another
|
|
408
|
+
* account, and neither class can be token-verified by any caller. Such a
|
|
409
|
+
* candidate is recorded as unverified instead of failing an otherwise clean
|
|
410
|
+
* capture; every other unreadable candidate stays fail-closed.
|
|
411
|
+
*/
|
|
412
|
+
const environmentWithheldFromInspection = (entry, diagnostic) => {
|
|
413
|
+
const uid = currentProcessUid();
|
|
414
|
+
if (uid !== undefined && entry.uid !== undefined && entry.uid !== uid)
|
|
415
|
+
return true;
|
|
416
|
+
return diagnostic === PLATFORM_BINARY_ENVIRONMENT_WITHHELD;
|
|
417
|
+
};
|
|
418
|
+
const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline, relation) => {
|
|
419
|
+
let candidates = processes;
|
|
420
|
+
let candidateIdentities = new Map();
|
|
421
|
+
if (host.processIdentities !== undefined) {
|
|
422
|
+
const current = await host.processIdentities(processes);
|
|
423
|
+
candidateIdentities = current;
|
|
424
|
+
if (captureBaseline !== undefined) {
|
|
425
|
+
const baseline = new Map(captureBaseline.map(({ pid, identity }) => [pid, identity]));
|
|
426
|
+
candidates = processes.filter((process) => {
|
|
427
|
+
const before = baseline.get(process.pid);
|
|
428
|
+
const now = current.get(process.pid);
|
|
429
|
+
return !(before !== undefined &&
|
|
430
|
+
before !== null &&
|
|
431
|
+
now?.state === "readable" &&
|
|
432
|
+
now.identity === before);
|
|
433
|
+
});
|
|
231
434
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
435
|
+
}
|
|
436
|
+
const failures = [];
|
|
437
|
+
if (captureBaseline !== undefined && host.processIdentities !== undefined) {
|
|
438
|
+
const stableCandidates = [];
|
|
439
|
+
for (const process of candidates) {
|
|
440
|
+
if (candidateIdentities.get(process.pid)?.state === "readable") {
|
|
441
|
+
stableCandidates.push(process);
|
|
442
|
+
continue;
|
|
237
443
|
}
|
|
238
|
-
|
|
444
|
+
if (!(await processIsGone(host, process.pid)))
|
|
239
445
|
failures.push({
|
|
240
446
|
pid: process.pid,
|
|
241
|
-
reason: "
|
|
242
|
-
diagnostic:
|
|
447
|
+
reason: "process-identity-unavailable",
|
|
448
|
+
diagnostic: "process identity was unavailable during token scan",
|
|
243
449
|
});
|
|
450
|
+
}
|
|
451
|
+
candidates = stableCandidates;
|
|
452
|
+
}
|
|
453
|
+
const owned = [];
|
|
454
|
+
const ownedIdentities = new Map();
|
|
455
|
+
const recordOwned = (process) => {
|
|
456
|
+
owned.push(process);
|
|
457
|
+
const identity = candidateIdentities.get(process.pid);
|
|
458
|
+
ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
|
|
459
|
+
};
|
|
460
|
+
let bulkTokens;
|
|
461
|
+
if (host.runTokens !== undefined)
|
|
462
|
+
bulkTokens = await host.runTokens(candidates);
|
|
463
|
+
const unreadable = [];
|
|
464
|
+
for (const process of candidates) {
|
|
465
|
+
const bulkToken = bulkTokens?.get(process.pid);
|
|
466
|
+
if (bulkToken !== undefined) {
|
|
467
|
+
if (bulkToken.state === "readable") {
|
|
468
|
+
if (bulkToken.runId === runId)
|
|
469
|
+
recordOwned(process);
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
unreadable.push({ process, diagnostic: bulkToken.reason });
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
|
|
477
|
+
recordOwned(process);
|
|
478
|
+
}
|
|
479
|
+
catch (cause) {
|
|
480
|
+
unreadable.push({ process, diagnostic: errorMessage(cause) });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const remaining = await settleUnreadableTokenCandidates(unreadable, runId, host, recordOwned);
|
|
484
|
+
const relatedPids = new Set();
|
|
485
|
+
const relatedGroupIds = new Set();
|
|
486
|
+
if (relation !== undefined) {
|
|
487
|
+
relatedPids.add(relation.leaderPid);
|
|
488
|
+
for (const descendant of descendantsOf(relation.leaderPid, processes))
|
|
489
|
+
relatedPids.add(descendant.pid);
|
|
490
|
+
relatedGroupIds.add(relation.processGroupId);
|
|
491
|
+
for (const processGroupId of relation.sampledProcessGroupIds ?? [])
|
|
492
|
+
if (Number.isSafeInteger(processGroupId) && processGroupId > 0)
|
|
493
|
+
relatedGroupIds.add(processGroupId);
|
|
494
|
+
for (const process of owned)
|
|
495
|
+
relatedGroupIds.add(process.processGroupId);
|
|
496
|
+
}
|
|
497
|
+
const unverified = [];
|
|
498
|
+
const strict = [];
|
|
499
|
+
const withheld = [];
|
|
500
|
+
for (const candidate of remaining) {
|
|
501
|
+
const isRelated = relation === undefined ||
|
|
502
|
+
relatedPids.has(candidate.process.pid) ||
|
|
503
|
+
relatedGroupIds.has(candidate.process.processGroupId);
|
|
504
|
+
if (!isRelated &&
|
|
505
|
+
environmentWithheldFromInspection(candidate.process, candidate.diagnostic)) {
|
|
506
|
+
withheld.push(candidate);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
strict.push(candidate);
|
|
510
|
+
}
|
|
511
|
+
let finalLive;
|
|
512
|
+
try {
|
|
513
|
+
finalLive = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
|
|
514
|
+
}
|
|
515
|
+
catch (cause) {
|
|
516
|
+
void cause;
|
|
517
|
+
finalLive = undefined;
|
|
518
|
+
}
|
|
519
|
+
for (const candidate of strict) {
|
|
520
|
+
if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
|
|
521
|
+
continue;
|
|
522
|
+
failures.push({
|
|
523
|
+
pid: candidate.process.pid,
|
|
524
|
+
reason: "environment-unreadable",
|
|
525
|
+
diagnostic: candidate.diagnostic,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
for (const candidate of withheld) {
|
|
529
|
+
if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
|
|
530
|
+
continue;
|
|
531
|
+
unverified.push({
|
|
532
|
+
pid: candidate.process.pid,
|
|
533
|
+
diagnostic: candidate.diagnostic,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
if (candidates.length > 0 && host.processIdentities !== undefined) {
|
|
537
|
+
const afterRead = await host.processIdentities(candidates);
|
|
538
|
+
const stillOwned = [];
|
|
539
|
+
const ownedPids = new Set(owned.map(({ pid }) => pid));
|
|
540
|
+
for (const process of candidates) {
|
|
541
|
+
const before = candidateIdentities.get(process.pid);
|
|
542
|
+
const current = afterRead.get(process.pid);
|
|
543
|
+
if (before?.state === "readable" &&
|
|
544
|
+
current?.state === "readable" &&
|
|
545
|
+
current.identity === before.identity) {
|
|
546
|
+
if (ownedPids.has(process.pid))
|
|
547
|
+
stillOwned.push(process);
|
|
244
548
|
continue;
|
|
245
549
|
}
|
|
550
|
+
if (await processIsGone(host, process.pid))
|
|
551
|
+
continue;
|
|
246
552
|
failures.push({
|
|
247
553
|
pid: process.pid,
|
|
248
|
-
reason: "
|
|
249
|
-
diagnostic:
|
|
554
|
+
reason: "process-identity-unavailable",
|
|
555
|
+
diagnostic: "process identity changed or became unavailable during token validation",
|
|
250
556
|
});
|
|
251
557
|
}
|
|
558
|
+
return {
|
|
559
|
+
owned: stillOwned,
|
|
560
|
+
failures,
|
|
561
|
+
unverified,
|
|
562
|
+
identities: ownedIdentities,
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
return { owned, failures, unverified, identities: ownedIdentities };
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* Re-read run tokens for unresolved sweep candidates so transient exec and
|
|
569
|
+
* exit states settle before classification. Each attempt revalidates
|
|
570
|
+
* liveness, refreshes the diagnostic, and is bounded by a fixed attempt
|
|
571
|
+
* budget; a still-unreadable candidate keeps its latest diagnostic.
|
|
572
|
+
*/
|
|
573
|
+
const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned) => {
|
|
574
|
+
let remaining = pending;
|
|
575
|
+
for (let attempt = 0; attempt < TOKEN_READ_RETRY_ATTEMPTS && remaining.length > 0; attempt += 1) {
|
|
576
|
+
await new Promise((resolve) => setTimeout(resolve, TOKEN_READ_RETRY_DELAY_MS));
|
|
577
|
+
let live;
|
|
578
|
+
try {
|
|
579
|
+
live = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
|
|
580
|
+
}
|
|
581
|
+
catch (cause) {
|
|
582
|
+
void cause;
|
|
583
|
+
live = undefined;
|
|
584
|
+
}
|
|
585
|
+
let observations;
|
|
586
|
+
if (host.runTokens !== undefined) {
|
|
587
|
+
try {
|
|
588
|
+
observations = await host.runTokens(remaining.map(({ process }) => process));
|
|
589
|
+
}
|
|
590
|
+
catch (cause) {
|
|
591
|
+
void cause;
|
|
592
|
+
observations = undefined;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
const stillUnreadable = [];
|
|
596
|
+
for (const candidate of remaining) {
|
|
597
|
+
const pid = candidate.process.pid;
|
|
598
|
+
if (live !== undefined && !live.has(pid))
|
|
599
|
+
continue;
|
|
600
|
+
const observation = observations?.get(pid) ?? (await readEnvironmentRunToken(host, pid));
|
|
601
|
+
if (observation.state === "readable") {
|
|
602
|
+
if (observation.runId === runId)
|
|
603
|
+
recordOwned(candidate.process);
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
stillUnreadable.push({
|
|
607
|
+
process: candidate.process,
|
|
608
|
+
diagnostic: observation.reason,
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
remaining = stillUnreadable;
|
|
612
|
+
}
|
|
613
|
+
return remaining;
|
|
614
|
+
};
|
|
615
|
+
const readEnvironmentRunToken = async (host, pid) => {
|
|
616
|
+
try {
|
|
617
|
+
return {
|
|
618
|
+
state: "readable",
|
|
619
|
+
runId: (await host.environment(pid)).REA_PROCESS_RUN_ID,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
catch (cause) {
|
|
623
|
+
return { state: "unavailable", reason: errorMessage(cause) };
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
const processIsGone = async (host, pid) => {
|
|
627
|
+
try {
|
|
628
|
+
return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
|
|
629
|
+
}
|
|
630
|
+
catch (cause) {
|
|
631
|
+
void cause;
|
|
632
|
+
return false;
|
|
252
633
|
}
|
|
253
|
-
return { owned, failures };
|
|
254
634
|
};
|