rea-agents 6.1.0 → 6.2.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 +7 -5
- package/bridge/ghidra/ReaGhidraBridge.java +32 -4
- package/bridge/hopper_bridge.py +6 -1
- package/dist/android/JadxConfiguration.js +87 -7
- package/dist/android/JadxMcpTransport.js +14 -2
- package/dist/android/JadxProvider.js +57 -35
- package/dist/application/BinaryTargetResolver.js +5 -3
- package/dist/application/BrowserEvidence.js +3 -8
- package/dist/application/BrowserScenarioEvidence.js +2 -18
- package/dist/application/CapabilityInventory.js +43 -9
- package/dist/application/ClientConfigurationDocument.js +69 -25
- package/dist/application/DirectAnalysis.js +29 -14
- package/dist/application/DirectAnalysisCleanup.js +72 -0
- package/dist/application/DirectAnalysisStatus.js +4 -5
- package/dist/application/Doctor.js +15 -19
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/EnhancedTools.js +51 -6
- package/dist/application/EvidenceBundleFiles.js +8 -3
- package/dist/application/InvestigationProviders.js +9 -1
- package/dist/application/JsonFiles.js +42 -9
- package/dist/application/LinuxHopper.js +9 -6
- package/dist/application/MacHopper.js +15 -18
- package/dist/application/RealHopperAssertions.js +0 -11
- package/dist/application/ReconstructionObligationCandidates.js +1 -1
- package/dist/application/ReferenceSourceImportEntries.js +1 -1
- package/dist/application/Setup.js +8 -16
- package/dist/application/SetupHost.js +16 -27
- package/dist/application/SetupPlan.js +6 -6
- package/dist/application/Uninstall.js +81 -29
- package/dist/application/UpdateMaintenance.js +7 -5
- package/dist/application/UpdateRuntime.js +12 -12
- package/dist/application/WebScriptExportService.js +30 -4
- package/dist/application/WorkflowEvidence.js +25 -2
- package/dist/application/XrefsAddressResolution.js +45 -0
- package/dist/application/analysisView/AnalysisViewService.js +76 -0
- package/dist/application/binary/AnalysisClientCleanup.js +30 -5
- package/dist/application/binary/AnalysisProviderEvaluation.js +1 -2
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -6
- package/dist/application/binary/AnalysisSnapshotCache.js +10 -8
- package/dist/application/binary/BinarySession.js +70 -29
- package/dist/application/binary/BinarySessionComposition.js +1 -3
- package/dist/application/binary/BinarySessionExecution.js +3 -5
- package/dist/application/binary/BinarySessionOpen.js +1 -1
- package/dist/application/binary/BinarySessionRecords.js +1 -1
- package/dist/application/binary/BinarySessionStatus.js +1 -6
- package/dist/application/binary/CompositeProvider.js +4 -18
- package/dist/application/binary/LazyAnalysisProvider.js +5 -5
- package/dist/application/binary/SessionProviderRouter.js +27 -135
- package/dist/application/homebrew.js +48 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +2 -6
- package/dist/application/javascript/JavaScriptApplicationService.js +6 -1
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -3
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +11 -9
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +43 -16
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +46 -6
- package/dist/application/javascript/JavaScriptModuleRelationships.js +1 -1
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +42 -19
- package/dist/application/managed/ManagedMemberComparisonService.js +2 -1
- package/dist/application/managed/ManagedNativeVerificationService.js +2 -1
- package/dist/application/process/ProcessCli.js +11 -11
- package/dist/application/process/ProcessEvidence.js +0 -1
- package/dist/artifacts/ArtifactProvider.js +39 -14
- package/dist/artifacts/ArtifactReader.js +31 -0
- package/dist/artifacts/DirectoryArtifactReader.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +9 -2
- package/dist/artifacts/NativeDmgArtifactReader.js +65 -20
- package/dist/artifacts/SafeOutputTree.js +16 -2
- package/dist/artifacts/ZipArtifactReader.js +11 -4
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +4 -2
- package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
- package/dist/artifacts/apple/KeyedArchiveReader.js +21 -3
- package/dist/artifacts/extraction/ArtifactExtraction.js +78 -21
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +67 -61
- package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
- package/dist/artifacts/inventory/reader.js +3 -3
- package/dist/artifacts/inventory/scanCanonical.js +48 -24
- package/dist/artifacts/inventory/scanReader.js +5 -9
- package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
- package/dist/browser/CdpBrowserProvider.js +2 -3
- package/dist/browser/CdpCaptureEventHandlers.js +2 -4
- package/dist/browser/CdpCaptureEvents.js +0 -1
- package/dist/browser/CdpCaptureValues.js +20 -0
- package/dist/browser/CdpElectronProvider.js +0 -2
- package/dist/browser/CdpElectronScriptEvents.js +2 -8
- package/dist/browser/CdpElectronScripts.js +2 -3
- package/dist/browser/CdpPageCaptureScripts.js +2 -3
- package/dist/browser/CdpSafeMetadata.js +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
- package/dist/browser/PlaywrightElectronActiveActions.js +2 -56
- package/dist/browser/PlaywrightElectronActiveProvider.js +10 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
- package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
- package/dist/browser/PlaywrightScenarioEvents.js +1 -1
- package/dist/browser/PlaywrightScenarioSession.js +39 -22
- package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
- package/dist/browser/history/CaptureFailures.js +6 -2
- package/dist/browser/history/MitmproxyCaptureAdapter.js +4 -2
- package/dist/catalogIdentity.js +0 -1
- package/dist/cli/analysisViewCommands.js +36 -0
- package/dist/cli/artifactCommands.js +11 -12
- package/dist/cli/coreAnalysisCommands.js +3 -3
- package/dist/cli/coreBinaryCommands.js +32 -27
- package/dist/cli/coreNativeCommands.js +9 -10
- package/dist/cli/electronCommands.js +4 -4
- package/dist/cli/interactiveSetup.js +6 -6
- package/dist/cli/managedCommands.js +7 -8
- package/dist/cli/nativeCallCommands.js +1 -2
- package/dist/cli/omittableDefaults.js +50 -0
- package/dist/cli/processCommands.js +3 -2
- package/dist/cli/setupCommands.js +16 -15
- package/dist/cli/utilityCommands.js +9 -9
- package/dist/cli.js +16 -8
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +1 -0
- package/dist/cliJsonInput.js +15 -1
- package/dist/cliOutput.js +0 -38
- package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
- package/dist/composition/binary.js +9 -9
- package/dist/composition/browserScenario.js +2 -1
- package/dist/composition/directAnalysis.js +20 -13
- package/dist/composition/electronScenario.js +1 -1
- package/dist/composition/optionalObservationProviders.js +12 -7
- package/dist/config/environment.js +6 -0
- package/dist/config/ghidraStartupTimeout.js +4 -9
- package/dist/config/homeDirectory.js +12 -0
- package/dist/config/mcpResponseBudget.js +9 -1
- package/dist/config/parseConfig.js +7 -3
- package/dist/config/parsers.js +19 -22
- package/dist/contracts/analysisViewToolContracts.js +56 -0
- package/dist/contracts/applicationToolContracts.js +5 -4
- package/dist/contracts/artifactComparisonExample.js +2 -2
- package/dist/contracts/artifactToolContracts.js +1 -1
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +19 -15
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/enhancedToolContracts.js +4 -3
- package/dist/contracts/evm/evmToolContracts.js +1 -1
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +90 -0
- package/dist/contracts/investigationExamples.js +4 -3
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
- package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +5 -10
- package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
- package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
- package/dist/contracts/native/nativeToolContracts.js +2 -2
- package/dist/contracts/officialToolContracts.js +2 -1
- package/dist/contracts/promptContracts.js +2 -2
- package/dist/contracts/providerSelection.js +1 -1
- package/dist/contracts/sessionToolContracts.js +14 -2
- package/dist/contracts/sessionToolSchemas.js +1 -14
- package/dist/contracts/toolContracts.js +2 -0
- package/dist/contracts/toolEffects.js +1 -0
- package/dist/contracts/toolOutputSchemaGroups.js +136 -92
- package/dist/contracts/toolOutputSchemaPrimitives.js +11 -21
- package/dist/contracts/toolSchemaMetadata.js +18 -69
- package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
- package/dist/contracts/webRuntimeToolContracts.js +1 -1
- package/dist/contracts/webScriptToolContracts.js +1 -1
- package/dist/doctorRuntime.js +7 -5
- package/dist/domain/analysisErrorCore.js +3 -0
- package/dist/domain/analysisErrorPresentation.js +18 -3
- package/dist/domain/analysisErrorProjection.js +24 -5
- package/dist/domain/analysisSnapshot.js +29 -31
- package/dist/domain/analysisView/analysisView.js +243 -0
- package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
- package/dist/domain/analysisView/binaryLayoutView.js +159 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
- package/dist/domain/android/androidApplication.js +1 -1
- package/dist/domain/apple/appleApplication.js +1 -1
- package/dist/domain/apple/dylibResolution.js +10 -3
- package/dist/domain/apple/interfaceBuilderGraph.js +0 -1
- package/dist/domain/apple/keyedArchive.js +26 -2
- package/dist/domain/artifactComparison.js +15 -6
- package/dist/domain/artifactGraph.js +16 -3
- package/dist/domain/artifactInventoryEvidence.js +9 -16
- package/dist/domain/artifactOperationError.js +3 -3
- package/dist/domain/artifactPartialObservation.js +1 -0
- package/dist/domain/artifactPathSyntax.js +49 -0
- package/dist/domain/binaryTarget.js +39 -13
- package/dist/domain/browserCaptureComparison.js +13 -49
- package/dist/domain/browserNetworkEvidence.js +10 -4
- package/dist/domain/browserObservation.js +0 -1
- package/dist/domain/browserObservationSchemas.js +14 -3
- package/dist/domain/browserScenario.js +0 -1
- package/dist/domain/browserScenarioCapture.js +1 -2
- package/dist/domain/browserScenarioDiff.js +0 -2
- package/dist/domain/browserScenarioDiffEvidence.js +0 -12
- package/dist/domain/browserScenarioDiffValues.js +2 -2
- package/dist/domain/browserScenarioValues.js +3 -4
- package/dist/domain/callPath.js +8 -9
- package/dist/domain/callPathSchemas.js +2 -2
- package/dist/domain/changedBehavior.js +3 -3
- package/dist/domain/completionLedgerGeneration.js +2 -1
- package/dist/domain/configurationErrors.js +12 -0
- package/dist/domain/conformancePackage.js +4 -3
- package/dist/domain/evidence.js +10 -36
- package/dist/domain/evidenceBundle.js +7 -9
- package/dist/domain/evidenceCompletionLedger.js +2 -1
- package/dist/domain/functionComparison.js +4 -5
- package/dist/domain/functionComparisonDimensions.js +120 -87
- package/dist/domain/functionComparisonNormalization.js +23 -34
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/functionComparisonSchemas.js +2 -8
- package/dist/domain/functionDossierEvidence.js +2 -37
- package/dist/domain/javascript/electronActiveObservation.js +26 -69
- package/dist/domain/javascript/electronObservation.js +14 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +26 -3
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
- package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
- package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
- package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
- package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
- package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
- package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +9 -3
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +1 -1
- package/dist/domain/javascript/javascriptSemanticGraph.js +88 -46
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +1 -12
- package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
- package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +1 -1
- package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
- package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -54
- package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +2 -1
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +0 -1
- package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
- package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
- package/dist/domain/localPath.js +1 -1
- package/dist/domain/managed/managedArtifact.js +6 -4
- package/dist/domain/managed/managedMemberComparison.js +2 -9
- package/dist/domain/managed/managedNativeVerification.js +0 -2
- package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
- package/dist/domain/native/binaryLayout.js +2 -3
- package/dist/domain/native/nativeApiBoundary.js +1 -1
- package/dist/domain/native/nativeCallObservation.js +5 -3
- package/dist/domain/native/nativeInstruction.js +7 -0
- package/dist/domain/native/recordedCrash.js +2 -3
- package/dist/domain/offsetDateTime.js +17 -0
- package/dist/domain/process/processCapture.js +13 -12
- package/dist/domain/process/processCaptureCoverage.js +67 -0
- package/dist/domain/process/processCaptureExample.js +2 -1
- package/dist/domain/process/processCaptureParsing.js +1 -34
- package/dist/domain/process/processCaptureValidation.js +81 -13
- package/dist/domain/process/processComparison.js +41 -22
- package/dist/domain/process/processObservation.js +10 -2
- package/dist/domain/process/processScenario.js +24 -2
- package/dist/domain/process/processTraceComparison.js +0 -2
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +15 -11
- package/dist/domain/process/processTraceSpecification.js +3 -4
- package/dist/domain/providerAdapterError.js +2 -0
- package/dist/domain/reconstructionCoverage.js +5 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
- package/dist/domain/reconstructionReadinessSchemas.js +2 -1
- package/dist/domain/reconstructionVerification.js +3 -3
- package/dist/domain/reconstructionVerificationSchemas.js +2 -1
- package/dist/domain/referenceSourceGraph.js +20 -21
- package/dist/domain/staticRuntimeCorrelation.js +2 -2
- package/dist/domain/stringPatterns.js +6 -0
- package/dist/domain/swiftSymbolClassification.js +61 -0
- package/dist/domain/symbolAnalysis.js +66 -18
- package/dist/domain/webCaptureDiff.js +0 -1
- package/dist/domain/webCaptureDiffSchemas.js +6 -3
- package/dist/domain/webEventListeners.js +3 -2
- package/dist/domain/webExecution.js +3 -2
- package/dist/domain/webRuntime.js +0 -2
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/dotnet/ManagedArtifactInspector.js +2 -19
- package/dist/dotnet/ManagedMemberInspector.js +12 -18
- package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
- package/dist/dotnet/ManagedMemberRows.js +75 -62
- package/dist/dotnet/ManagedMetadataInventory.js +16 -22
- package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
- package/dist/dotnet/ManagedReaderFailure.js +16 -0
- package/dist/dotnet/ManagedStaticProvider.js +3 -5
- package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
- package/dist/evaluation/AgentEvaluationReport.js +28 -0
- package/dist/evaluation/CodexAgentEval.js +12 -8
- package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
- package/dist/evm/EvmoleInterfaceProvider.js +2 -1
- package/dist/firmware/FirmwareCommand.js +9 -5
- package/dist/firmware/FirmwareProvider.js +4 -4
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +3 -6
- package/dist/ghidra/GhidraClient.js +91 -32
- package/dist/ghidra/GhidraClientStartup.js +0 -2
- package/dist/ghidra/GhidraDoctor.js +6 -5
- package/dist/ghidra/GhidraFunctionValues.js +3 -5
- package/dist/ghidra/GhidraInstallation.js +40 -12
- package/dist/ghidra/GhidraJavaLaunch.js +6 -2
- package/dist/ghidra/GhidraLauncher.js +15 -7
- package/dist/ghidra/GhidraProvider.js +6 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +6 -0
- package/dist/ghidra/GhidraProviderClient.js +13 -3
- package/dist/ghidra/GhidraSessionError.js +2 -0
- package/dist/ghidra/GhidraSessionRoot.js +39 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
- package/dist/hopper/BridgeLauncher.js +34 -45
- package/dist/hopper/HopperAnalysisProfile.js +3 -8
- package/dist/hopper/HopperCleanup.js +56 -27
- package/dist/hopper/HopperClient.js +86 -65
- package/dist/hopper/HopperMachOImage.js +3 -2
- package/dist/hopper/HopperProvider.js +16 -18
- package/dist/hopper/HopperRegexSearch.js +3 -6
- package/dist/hopper/HopperTargetLease.js +132 -49
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
- package/dist/ida/IdaConfiguration.js +8 -3
- package/dist/ida/IdaInput.js +1 -7
- package/dist/ida/IdaMcpConnection.js +8 -4
- package/dist/ida/IdaOperationRunner.js +3 -3
- package/dist/ida/IdaProvider.js +8 -12
- package/dist/ida/IdaSessionClient.js +20 -18
- package/dist/ida/IdaWorkspace.js +12 -13
- package/dist/inspector/V8InspectorCaptureProjection.js +1 -1
- package/dist/inspector/V8InspectorProvider.js +38 -28
- package/dist/javascript/recovery/WakaruCommand.js +7 -2
- package/dist/javascript/recovery/WakaruExecution.js +5 -2
- package/dist/main/shutdown.js +11 -3
- package/dist/main/startup.js +9 -2
- package/dist/main/transport.js +22 -2
- package/dist/main.js +11 -18
- package/dist/native/AppleMachoSelection.js +16 -6
- package/dist/native/CommandRunner.js +9 -7
- package/dist/native/LldbCallTracer.js +8 -2
- package/dist/native/NativeMacOSProvider.js +25 -15
- package/dist/native/NativeUiHelperRuntime.js +11 -2
- package/dist/native/NativeUiObservation.js +2 -2
- package/dist/native/pwntools/PwntoolsDecoder.js +2 -1
- package/dist/process/DarwinProcessRunTokenReader.js +16 -2
- package/dist/process/ExecFileOutput.js +88 -6
- package/dist/process/PrivateRuntimeRoot.js +10 -5
- package/dist/process/ProcessOwnership.js +1 -4
- package/dist/process/ProcessOwnershipObservation.js +11 -5
- package/dist/process/ProviderProcess.js +1 -3
- package/dist/process/capture/FilesystemSnapshot.js +50 -13
- package/dist/process/capture/ProcessCaptureError.js +13 -0
- package/dist/process/capture/ProcessCaptureLifecycle.js +158 -70
- package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
- package/dist/process/capture/ProcessHarness.js +21 -25
- package/dist/process/capture/ProcessNormalization.js +20 -2
- package/dist/process/capture/ProcessSampling.js +25 -2
- package/dist/process/capture/TerminalRenderer.js +14 -0
- package/dist/process/snapshotEnvironment.js +14 -0
- package/dist/server/EvidenceMcpServer.js +25 -14
- package/dist/server/createServer.js +49 -36
- package/dist/server/mcpClientMetadata.js +12 -5
- package/dist/server/promptCompletion.js +3 -8
- package/dist/server/registerAnalysisViewTool.js +15 -0
- package/dist/server/registerAndroidTools.js +2 -3
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +4 -5
- package/dist/server/registerApplicationTools/coverage.js +1 -2
- package/dist/server/registerApplicationTools/helpers.js +1 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
- package/dist/server/registerApplicationTools/traceFeature.js +4 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +4 -5
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -3
- package/dist/server/registerBrowserScenarioTool.js +3 -4
- package/dist/server/registerBrowserTools.js +13 -16
- package/dist/server/registerBundleComparisonTool.js +5 -6
- package/dist/server/registerCloseLifecycleTool.js +2 -3
- package/dist/server/registerElectronTools.js +10 -13
- package/dist/server/registerEnhancedTools.js +23 -23
- package/dist/server/registerEvidenceTools.js +3 -4
- package/dist/server/registerEvmTools.js +2 -3
- package/dist/server/registerFirmwareTools.js +2 -3
- package/dist/server/registerFunctionComparisonTool.js +7 -8
- package/dist/server/registerInvestigationTools.js +14 -15
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -3
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -6
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -5
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -7
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -7
- package/dist/server/registerOfficialTools.js +4 -19
- package/dist/server/registerProcessComparisonTool.js +8 -8
- package/dist/server/registerRecordedCrashTools.js +2 -3
- package/dist/server/registerSessionRecordTools.js +15 -19
- package/dist/server/registerSessionStatusTool.js +3 -4
- package/dist/server/registerSessionTools.js +12 -18
- package/dist/server/registerWebModuleTool.js +2 -3
- package/dist/server/registerWebNetworkCaptureTool.js +2 -3
- package/dist/server/registerWebRuntimeTools.js +4 -5
- package/dist/server/registerWebScriptTool.js +2 -3
- package/dist/server/registerWebSourceLocationTool.js +2 -3
- package/dist/server/toolResult.js +66 -94
- package/dist/server/toolResultEncoding.js +11 -10
- package/dist/windows/WindowsNativeLoader.js +1 -0
- package/dist/windows/WindowsOwnedProcess.js +60 -15
- package/dist/windows/WindowsPrivateRuntime.js +7 -8
- package/native/windows/README.md +3 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +39 -30
- package/scripts/rea.mjs +3 -6
- package/skills/reverse-engineer-anything/SKILL.md +9 -8
- package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +16 -6
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/config.js +0 -1
- package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
- package/dist/contracts/process/processCaptureExample.js +0 -2
- package/dist/contracts/toolOutputSchemas.js +0 -2
- package/dist/main/reload.js +0 -12
- package/dist/main/state.js +0 -3
- package/dist/server/sessionToolPolicies.js +0 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
3
|
+
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
|
3
4
|
import { err, ok } from "../domain/result.js";
|
|
4
5
|
import { silentLogger } from "../logger.js";
|
|
5
6
|
import { PendingOperations } from "../process/PendingOperations.js";
|
|
@@ -20,8 +21,9 @@ import { connectGhidraSocket } from "./GhidraSocketConnection.js";
|
|
|
20
21
|
import { createGhidraEndpoint, } from "./GhidraTransport.js";
|
|
21
22
|
import { GhidraWire } from "./GhidraClientWire.js";
|
|
22
23
|
import { completeGhidraStartupHandshake } from "./GhidraClientStartup.js";
|
|
24
|
+
import { ghidraSessionRoot } from "./GhidraSessionRoot.js";
|
|
23
25
|
const SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
24
|
-
const SESSION_ROOT =
|
|
26
|
+
const SESSION_ROOT = ghidraSessionRoot();
|
|
25
27
|
/** Owns an authenticated private Ghidra session with transport-bound mutation authority. */
|
|
26
28
|
export class GhidraClient {
|
|
27
29
|
#options;
|
|
@@ -91,10 +93,12 @@ export class GhidraClient {
|
|
|
91
93
|
/** Launch Ghidra once and require its exact post-analysis handshake. */
|
|
92
94
|
start(signal) {
|
|
93
95
|
if (this.#closePromise !== undefined)
|
|
94
|
-
return this.#closePromise.then(() => this.start(signal));
|
|
96
|
+
return this.#closePromise.then(() => this.start(signal), (cause) => err(new GhidraSessionError("process", "Ghidra cleanup remains incomplete", this.#diagnostics(), { cause, cleanupFailure: this.#cleanupError(cause) })));
|
|
95
97
|
if (this.#startPromise !== undefined) {
|
|
96
98
|
if (this.#startupController?.signal.aborted && !signal?.aborted)
|
|
97
|
-
return this.#startPromise.then((result) => result.ok
|
|
99
|
+
return this.#startPromise.then((result) => result.ok || result.error.cleanupFailure !== undefined
|
|
100
|
+
? result
|
|
101
|
+
: this.start(signal));
|
|
98
102
|
return this.#startPromise;
|
|
99
103
|
}
|
|
100
104
|
const controller = new AbortController();
|
|
@@ -153,8 +157,43 @@ export class GhidraClient {
|
|
|
153
157
|
}
|
|
154
158
|
}
|
|
155
159
|
/** Stop the owned process group and remove all project/runtime artifacts. */
|
|
156
|
-
close() {
|
|
157
|
-
|
|
160
|
+
async close() {
|
|
161
|
+
try {
|
|
162
|
+
await this.#requestClose(false);
|
|
163
|
+
return ok(null);
|
|
164
|
+
}
|
|
165
|
+
catch (cause) {
|
|
166
|
+
return err(this.#cleanupError(cause));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
#cleanupError(cause) {
|
|
170
|
+
if (cause instanceof AnalysisError && cause.cleanupIncomplete)
|
|
171
|
+
return cause;
|
|
172
|
+
return new ProviderCleanupError("ghidra", [
|
|
173
|
+
...(this.#process === undefined ? [] : ["ghidra-process"]),
|
|
174
|
+
...[this.#runtimeRoot, this.#socketRoot].flatMap((root) => root === undefined ? [] : [root.path]),
|
|
175
|
+
], {
|
|
176
|
+
reason: cause instanceof Error ? cause.message : String(cause),
|
|
177
|
+
diagnostics: this.#diagnostics(),
|
|
178
|
+
}, { cause });
|
|
179
|
+
}
|
|
180
|
+
async #startupFailure(primary) {
|
|
181
|
+
try {
|
|
182
|
+
await this.#cleanup();
|
|
183
|
+
return err(primary);
|
|
184
|
+
}
|
|
185
|
+
catch (cause) {
|
|
186
|
+
return err(new GhidraSessionError(primary.kind, primary.message, primary.diagnostics, {
|
|
187
|
+
...(primary.cause === undefined ? {} : { cause: primary.cause }),
|
|
188
|
+
...(primary.timeoutMs === undefined
|
|
189
|
+
? {}
|
|
190
|
+
: { timeoutMs: primary.timeoutMs }),
|
|
191
|
+
...(primary.remoteCode === undefined
|
|
192
|
+
? {}
|
|
193
|
+
: { remoteCode: primary.remoteCode }),
|
|
194
|
+
cleanupFailure: this.#cleanupError(cause),
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
158
197
|
}
|
|
159
198
|
#requestClose(forceStop) {
|
|
160
199
|
const starting = this.#startPromise;
|
|
@@ -218,8 +257,7 @@ export class GhidraClient {
|
|
|
218
257
|
}
|
|
219
258
|
catch (cause) {
|
|
220
259
|
const failure = this.#failure("start", "Ghidra private endpoint allocation failed", cause);
|
|
221
|
-
|
|
222
|
-
return err(failure);
|
|
260
|
+
return this.#startupFailure(failure);
|
|
223
261
|
}
|
|
224
262
|
try {
|
|
225
263
|
const snapshot = await createGhidraTargetSnapshot(this.#options.targetPath, this.#runtimeRoot.path, this.#options.targetSha256, { signal: deadline.signal, platform: this.#options.platform });
|
|
@@ -230,8 +268,7 @@ export class GhidraClient {
|
|
|
230
268
|
if (deadline.signal.aborted)
|
|
231
269
|
return this.#startupInterrupted(deadline);
|
|
232
270
|
const failure = this.#failure("start", "Ghidra target snapshot failed admission", cause);
|
|
233
|
-
|
|
234
|
-
return err(failure);
|
|
271
|
+
return this.#startupFailure(failure);
|
|
235
272
|
}
|
|
236
273
|
if (deadline.signal.aborted)
|
|
237
274
|
return this.#startupInterrupted(deadline);
|
|
@@ -258,8 +295,7 @@ export class GhidraClient {
|
|
|
258
295
|
: launched.error instanceof GhidraSessionError
|
|
259
296
|
? launched.error
|
|
260
297
|
: this.#failure("start", launched.error.message, launched.error);
|
|
261
|
-
|
|
262
|
-
return err(failure);
|
|
298
|
+
return this.#startupFailure(failure);
|
|
263
299
|
}
|
|
264
300
|
this.#launch = launched.value;
|
|
265
301
|
this.#process = new ProviderProcessSupervisor(launched.value, {
|
|
@@ -268,21 +304,19 @@ export class GhidraClient {
|
|
|
268
304
|
const connected = await this.#connect(endpoint, deadline);
|
|
269
305
|
if (!connected.ok) {
|
|
270
306
|
const failure = connected.error;
|
|
271
|
-
|
|
272
|
-
return err(failure);
|
|
307
|
+
return this.#startupFailure(failure);
|
|
273
308
|
}
|
|
274
309
|
const completed = await completeGhidraStartupHandshake({
|
|
275
310
|
deadline,
|
|
276
311
|
request: (method, params, requestOptions) => this.#wire.request(method, params, requestOptions),
|
|
277
312
|
parseSessionInfo: (value) => this.#parseSessionInfo(value),
|
|
278
|
-
cleanup: () => this.#cleanup(),
|
|
279
313
|
failure: this.#failure,
|
|
280
314
|
startupTimeoutMs: this.#options.startupTimeoutMs,
|
|
281
315
|
});
|
|
282
|
-
if (completed.ok)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
316
|
+
if (!completed.ok)
|
|
317
|
+
return this.#startupFailure(completed.error);
|
|
318
|
+
await this.#lineage.observe(this.#launch);
|
|
319
|
+
this.#requestQueue.reopen();
|
|
286
320
|
return completed;
|
|
287
321
|
}
|
|
288
322
|
async #connect(endpoint, deadline) {
|
|
@@ -389,18 +423,8 @@ export class GhidraClient {
|
|
|
389
423
|
this.#lastDiagnostics = this.#diagnostics();
|
|
390
424
|
this.#process = undefined;
|
|
391
425
|
this.#launch = undefined;
|
|
392
|
-
const runtimeRoot = this.#runtimeRoot;
|
|
393
|
-
const socketRoot = this.#socketRoot;
|
|
394
|
-
this.#runtimeRoot = undefined;
|
|
395
|
-
this.#socketRoot = undefined;
|
|
396
426
|
try {
|
|
397
|
-
|
|
398
|
-
runtimeRoot?.close(),
|
|
399
|
-
socketRoot?.close(),
|
|
400
|
-
]);
|
|
401
|
-
const failed = removed.find((result) => result.status === "rejected");
|
|
402
|
-
if (failed?.status === "rejected")
|
|
403
|
-
throw failed.reason;
|
|
427
|
+
await this.#removeRuntimeRoots();
|
|
404
428
|
}
|
|
405
429
|
catch (cause) {
|
|
406
430
|
if (forceStop)
|
|
@@ -420,6 +444,42 @@ export class GhidraClient {
|
|
|
420
444
|
this.#closing = false;
|
|
421
445
|
}
|
|
422
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Remove the runtime and socket roots, keeping each one that could not be
|
|
449
|
+
* removed so a later close retries it rather than reporting success.
|
|
450
|
+
*/
|
|
451
|
+
async #removeRuntimeRoots() {
|
|
452
|
+
const roots = [
|
|
453
|
+
{
|
|
454
|
+
root: this.#runtimeRoot,
|
|
455
|
+
release: () => (this.#runtimeRoot = undefined),
|
|
456
|
+
},
|
|
457
|
+
{ root: this.#socketRoot, release: () => (this.#socketRoot = undefined) },
|
|
458
|
+
];
|
|
459
|
+
const leftovers = [];
|
|
460
|
+
let firstCause;
|
|
461
|
+
for (const { root, release } of roots) {
|
|
462
|
+
if (root === undefined)
|
|
463
|
+
continue;
|
|
464
|
+
try {
|
|
465
|
+
await root.close();
|
|
466
|
+
release();
|
|
467
|
+
}
|
|
468
|
+
catch (cause) {
|
|
469
|
+
firstCause ??= cause;
|
|
470
|
+
leftovers.push({
|
|
471
|
+
path: root.path,
|
|
472
|
+
reason: cause instanceof Error ? cause.message : String(cause),
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (leftovers.length > 0)
|
|
477
|
+
throw new ProviderCleanupError("ghidra", leftovers.map(({ path }) => path), {
|
|
478
|
+
reason: "Ghidra's private runtime directory could not be removed; it is retained for a later close.",
|
|
479
|
+
leftover_paths: leftovers.map(({ path }) => path),
|
|
480
|
+
failures: leftovers.map(({ path, reason }) => `${path}: ${reason}`),
|
|
481
|
+
}, { cause: firstCause });
|
|
482
|
+
}
|
|
423
483
|
#redactAuthentication(value) {
|
|
424
484
|
for (const token of this.#authenticationTokens)
|
|
425
485
|
value = value.replaceAll(token, "[REDACTED]");
|
|
@@ -457,8 +517,7 @@ export class GhidraClient {
|
|
|
457
517
|
}
|
|
458
518
|
async #startupInterrupted(deadline) {
|
|
459
519
|
const failure = this.#interruptionFailure(deadline);
|
|
460
|
-
|
|
461
|
-
return err(failure);
|
|
520
|
+
return this.#startupFailure(failure);
|
|
462
521
|
}
|
|
463
522
|
#interruptionFailure(deadline) {
|
|
464
523
|
return deadline.interruption === "cancelled"
|
|
@@ -9,7 +9,6 @@ export async function completeGhidraStartupHandshake(options) {
|
|
|
9
9
|
const failure = options.deadline.signal.aborted
|
|
10
10
|
? interruptionFailure(options)
|
|
11
11
|
: ping.error;
|
|
12
|
-
await options.cleanup();
|
|
13
12
|
return err(failure);
|
|
14
13
|
}
|
|
15
14
|
const parsed = options.parseSessionInfo(ping.value);
|
|
@@ -17,7 +16,6 @@ export async function completeGhidraStartupHandshake(options) {
|
|
|
17
16
|
const failure = parsed.ok
|
|
18
17
|
? options.failure("analysis_timeout", "Ghidra auto-analysis reached its per-file deadline")
|
|
19
18
|
: parsed.error;
|
|
20
|
-
await options.cleanup();
|
|
21
19
|
return err(failure);
|
|
22
20
|
}
|
|
23
21
|
return parsed;
|
|
@@ -38,13 +38,14 @@ export const projectGhidraDoctorInspection = (inspection) => {
|
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
/** Inspect the process-configured BYO Ghidra installation for `rea doctor`. */
|
|
41
|
-
export const inspectSystemGhidraProvider = () => Promise.resolve(projectGhidraDoctorInspection(inspectGhidraInstallation({
|
|
42
|
-
|
|
41
|
+
export const inspectSystemGhidraProvider = (environment) => Promise.resolve(projectGhidraDoctorInspection(inspectGhidraInstallation({
|
|
42
|
+
environment,
|
|
43
|
+
...(environment.GHIDRA_INSTALL_DIR === undefined
|
|
43
44
|
? {}
|
|
44
|
-
: { installDir:
|
|
45
|
-
...(
|
|
45
|
+
: { installDir: environment.GHIDRA_INSTALL_DIR }),
|
|
46
|
+
...(environment.JAVA_HOME === undefined
|
|
46
47
|
? {}
|
|
47
|
-
: { javaHome:
|
|
48
|
+
: { javaHome: environment.JAVA_HOME }),
|
|
48
49
|
})));
|
|
49
50
|
const selectedChecks = (inspection) => {
|
|
50
51
|
const byName = new Map(inspection.checks.map((candidate) => [candidate.name, candidate]));
|
|
@@ -112,13 +112,11 @@ const procedureReferences = z
|
|
|
112
112
|
procedure: procedureIdentity,
|
|
113
113
|
direction: z.enum(["incoming", "outgoing"]),
|
|
114
114
|
references: z.array(referenceEdge),
|
|
115
|
-
reference_kinds_available: z.boolean()
|
|
116
|
-
unresolved_calls: z
|
|
117
|
-
.array(z.strictObject({
|
|
115
|
+
reference_kinds_available: z.boolean(),
|
|
116
|
+
unresolved_calls: z.array(z.strictObject({
|
|
118
117
|
address: ghidraCanonicalAddressSchema,
|
|
119
118
|
reason: z.string(),
|
|
120
|
-
}))
|
|
121
|
-
.default([]),
|
|
119
|
+
})),
|
|
122
120
|
})
|
|
123
121
|
.strict();
|
|
124
122
|
const procedureInfo = z
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
1
2
|
import { spawnSync } from "node:child_process";
|
|
2
3
|
import { constants } from "node:fs";
|
|
3
4
|
import { accessSync, readFileSync } from "node:fs";
|
|
4
5
|
import { posix, win32 } from "node:path";
|
|
5
6
|
import { ghidraApplicationProperties, ghidraJavaMajorAccepted, ghidraJavaRangeLabel, ghidraJavaRequirement, ghidraReleaseAccepted, ghidraReleaseCompatibility, ghidraReleaseLine, ghidraVersionDetail, SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION, } from "./GhidraInstallationPolicy.js";
|
|
6
|
-
export { SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION };
|
|
7
7
|
const NATIVE_PLATFORMS = {
|
|
8
8
|
linux: { x64: "linux_x86_64", arm64: "linux_arm_64" },
|
|
9
9
|
darwin: { x64: "mac_x86_64", arm64: "mac_arm_64" },
|
|
@@ -97,17 +97,15 @@ const installationCoordinates = (options, platform, architecture, host) => {
|
|
|
97
97
|
? undefined
|
|
98
98
|
: ghidraApplicationProperties(properties),
|
|
99
99
|
javaCommand,
|
|
100
|
-
|
|
100
|
+
// The configuration check rejects a relative JAVA_HOME. Probing it would
|
|
101
|
+
// run whatever `bin/java` the current directory holds.
|
|
102
|
+
java: options.javaHome === undefined || path.isAbsolute(options.javaHome)
|
|
103
|
+
? host.probeJava(javaCommand, ghidraJavaEnvironment(options.javaHome, options.environment, platform))
|
|
104
|
+
: undefined,
|
|
101
105
|
};
|
|
102
106
|
};
|
|
103
107
|
const installationChecks = ({ coordinates, platform, architecture, javaHome, host, }) => [
|
|
104
|
-
|
|
105
|
-
name: "configuration",
|
|
106
|
-
passed: coordinates.installDir !== null,
|
|
107
|
-
code: "not_configured",
|
|
108
|
-
detail: coordinates.installDir ?? "GHIDRA_INSTALL_DIR is not set",
|
|
109
|
-
remediation: `Set GHIDRA_INSTALL_DIR to an extracted Ghidra ${ghidraReleaseLine()} release directory.`,
|
|
110
|
-
}),
|
|
108
|
+
configurationCheck(coordinates.installDir, javaHome, platform),
|
|
111
109
|
installationCheck({
|
|
112
110
|
name: "platform",
|
|
113
111
|
passed: NATIVE_PLATFORMS[platform] !== undefined,
|
|
@@ -149,6 +147,35 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
149
147
|
}),
|
|
150
148
|
javaCheck(coordinates.java, coordinates.javaCommand, javaHome, coordinates.properties),
|
|
151
149
|
];
|
|
150
|
+
/**
|
|
151
|
+
* REA's configuration parser, and so the MCP server and analysis, accept only
|
|
152
|
+
* absolute paths; a relative one that happens to resolve here must not pass.
|
|
153
|
+
*/
|
|
154
|
+
const configurationCheck = (installDir, javaHome, platform) => {
|
|
155
|
+
const { isAbsolute } = platform === "win32" ? win32 : posix;
|
|
156
|
+
const relative = [
|
|
157
|
+
...(installDir !== null && !isAbsolute(installDir)
|
|
158
|
+
? ["GHIDRA_INSTALL_DIR"]
|
|
159
|
+
: []),
|
|
160
|
+
...(javaHome !== undefined && !isAbsolute(javaHome) ? ["JAVA_HOME"] : []),
|
|
161
|
+
];
|
|
162
|
+
if (installDir === null || relative.length === 0)
|
|
163
|
+
return installationCheck({
|
|
164
|
+
name: "configuration",
|
|
165
|
+
passed: installDir !== null,
|
|
166
|
+
code: "not_configured",
|
|
167
|
+
detail: installDir ?? "GHIDRA_INSTALL_DIR is not set",
|
|
168
|
+
remediation: `Set GHIDRA_INSTALL_DIR to an extracted Ghidra ${ghidraReleaseLine()} release directory.`,
|
|
169
|
+
});
|
|
170
|
+
const settings = relative.join(" and ");
|
|
171
|
+
return installationCheck({
|
|
172
|
+
name: "configuration",
|
|
173
|
+
passed: false,
|
|
174
|
+
code: "not_configured",
|
|
175
|
+
detail: `${settings} must be absolute`,
|
|
176
|
+
remediation: `Set ${settings} to ${relative.length === 1 ? "an absolute path" : "absolute paths"}. REA's analysis and MCP server reject relative paths even when they resolve from the current directory.`,
|
|
177
|
+
});
|
|
178
|
+
};
|
|
152
179
|
/** Project an installation probe into caller-visible, secret-free diagnostics. */
|
|
153
180
|
export const ghidraInstallationDiagnostics = (inspection) => ({
|
|
154
181
|
install_dir: inspection.installDir,
|
|
@@ -169,9 +196,10 @@ export const ghidraInstallationDiagnostics = (inspection) => ({
|
|
|
169
196
|
})),
|
|
170
197
|
});
|
|
171
198
|
/** Environment that makes an explicitly selected JDK win over PATH discovery. */
|
|
172
|
-
export const ghidraJavaEnvironment = (javaHome, environment
|
|
199
|
+
export const ghidraJavaEnvironment = (javaHome, environment, platform = process.platform) => {
|
|
200
|
+
const selectedEnvironment = snapshotEnvironment(environment, platform);
|
|
173
201
|
const boundedEnvironment = {
|
|
174
|
-
...
|
|
202
|
+
...selectedEnvironment,
|
|
175
203
|
_JAVA_OPTIONS: "",
|
|
176
204
|
JAVA_TOOL_OPTIONS: "",
|
|
177
205
|
JDK_JAVA_OPTIONS: "",
|
|
@@ -182,7 +210,7 @@ export const ghidraJavaEnvironment = (javaHome, environment = process.env, platf
|
|
|
182
210
|
: {
|
|
183
211
|
...boundedEnvironment,
|
|
184
212
|
JAVA_HOME: javaHome,
|
|
185
|
-
PATH: `${(platform === "win32" ? win32 : posix).join(javaHome, "bin")}${platform === "win32" ? win32.delimiter : posix.delimiter}${
|
|
213
|
+
PATH: `${(platform === "win32" ? win32 : posix).join(javaHome, "bin")}${platform === "win32" ? win32.delimiter : posix.delimiter}${selectedEnvironment.PATH ?? ""}`,
|
|
186
214
|
};
|
|
187
215
|
};
|
|
188
216
|
const installationCheck = (options) => options.passed
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
1
2
|
import { dirname, join } from "node:path";
|
|
2
3
|
import { execFileOutput } from "../process/ExecFileOutput.js";
|
|
3
4
|
/** Launch coordinates obtained from Ghidra's own release configuration helper. */
|
|
@@ -16,7 +17,9 @@ export const ghidraJavaLaunch = async (options) => {
|
|
|
16
17
|
"LaunchSupport",
|
|
17
18
|
installRoot,
|
|
18
19
|
];
|
|
19
|
-
const environment = {
|
|
20
|
+
const environment = {
|
|
21
|
+
...snapshotEnvironment(options.environment, options.platform),
|
|
22
|
+
};
|
|
20
23
|
const configuredEnvironment = await execFileOutput(command, [...supportArguments, "-envvars"], {
|
|
21
24
|
env: environment,
|
|
22
25
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
@@ -25,7 +28,8 @@ export const ghidraJavaLaunch = async (options) => {
|
|
|
25
28
|
if (line === "")
|
|
26
29
|
continue;
|
|
27
30
|
const separator = line.indexOf("=");
|
|
28
|
-
const
|
|
31
|
+
const sourceKey = line.slice(0, separator);
|
|
32
|
+
const key = options.platform === "win32" ? sourceKey.toUpperCase() : sourceKey;
|
|
29
33
|
if (separator < 1 || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key))
|
|
30
34
|
throw new Error(`Invalid Ghidra LaunchSupport environment entry: ${line}`);
|
|
31
35
|
if ((environment[key] ?? "") === "")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
1
2
|
import { mkdir } from "node:fs/promises";
|
|
2
3
|
import { basename, dirname, join, win32 } from "node:path";
|
|
3
4
|
import writeFileAtomic from "write-file-atomic";
|
|
@@ -20,7 +21,10 @@ export class GhidraLaunchError extends Error {
|
|
|
20
21
|
export class GhidraHeadlessLauncher {
|
|
21
22
|
options;
|
|
22
23
|
constructor(options) {
|
|
23
|
-
this.options =
|
|
24
|
+
this.options = {
|
|
25
|
+
...options,
|
|
26
|
+
environment: snapshotEnvironment(options.environment, options.platform),
|
|
27
|
+
};
|
|
24
28
|
}
|
|
25
29
|
async launch(session, options = {}) {
|
|
26
30
|
if (isAborted(options.signal))
|
|
@@ -60,6 +64,7 @@ export class GhidraHeadlessLauncher {
|
|
|
60
64
|
: { dosMz: this.options.dosMz }),
|
|
61
65
|
});
|
|
62
66
|
const scriptCommand = ghidraHeadlessCommand({
|
|
67
|
+
environment: this.options.environment,
|
|
63
68
|
platform,
|
|
64
69
|
analyzeHeadlessPath: this.options.analyzeHeadlessPath,
|
|
65
70
|
arguments: headlessArguments,
|
|
@@ -67,7 +72,7 @@ export class GhidraHeadlessLauncher {
|
|
|
67
72
|
? {}
|
|
68
73
|
: { comSpec: this.options.comSpec }),
|
|
69
74
|
});
|
|
70
|
-
const environment = ghidraLaunchEnvironment(paths, this.options.javaHome, platform, scriptCommand.command);
|
|
75
|
+
const environment = ghidraLaunchEnvironment(paths, this.options.javaHome, platform, scriptCommand.command, this.options.environment);
|
|
71
76
|
if (platform !== "win32" && this.options.javaHome === undefined)
|
|
72
77
|
throw new GhidraLaunchError("POSIX Ghidra requires its inspected JDK home");
|
|
73
78
|
const command = platform !== "win32" && this.options.javaHome !== undefined
|
|
@@ -94,6 +99,7 @@ export class GhidraHeadlessLauncher {
|
|
|
94
99
|
windowsVerbatimArguments: platform === "win32",
|
|
95
100
|
platform,
|
|
96
101
|
env: command.environment,
|
|
102
|
+
hostEnvironment: {},
|
|
97
103
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
98
104
|
});
|
|
99
105
|
await writeGhidraRuntimeFile(paths.ownershipPath, `${JSON.stringify({
|
|
@@ -145,11 +151,13 @@ export const ghidraHeadlessCommand = (options) => {
|
|
|
145
151
|
command: options.analyzeHeadlessPath,
|
|
146
152
|
arguments: [...options.arguments],
|
|
147
153
|
};
|
|
154
|
+
const environment = snapshotEnvironment(options.environment, options.platform);
|
|
155
|
+
const systemRoot = environment.SYSTEMROOT;
|
|
148
156
|
const comSpec = options.comSpec ??
|
|
149
|
-
|
|
150
|
-
(
|
|
157
|
+
environment.COMSPEC ??
|
|
158
|
+
(systemRoot === undefined
|
|
151
159
|
? "C:\\Windows\\System32\\cmd.exe"
|
|
152
|
-
: win32.join(
|
|
160
|
+
: win32.join(systemRoot, "System32", "cmd.exe"));
|
|
153
161
|
if (!win32.isAbsolute(comSpec) ||
|
|
154
162
|
win32.basename(comSpec).toLowerCase() !== "cmd.exe")
|
|
155
163
|
throw new GhidraLaunchError("Windows ComSpec must be an absolute cmd.exe path");
|
|
@@ -265,9 +273,9 @@ const writeGhidraRuntimeFile = async (path, content, platform) => {
|
|
|
265
273
|
}
|
|
266
274
|
await writeFileAtomic(path, content, { encoding: "utf8", mode: 0o600 });
|
|
267
275
|
};
|
|
268
|
-
const ghidraLaunchEnvironment = (paths, javaHome, platform, executable) => {
|
|
276
|
+
const ghidraLaunchEnvironment = (paths, javaHome, platform, executable, selectedEnvironment) => {
|
|
269
277
|
return {
|
|
270
|
-
...ghidraJavaEnvironment(javaHome,
|
|
278
|
+
...ghidraJavaEnvironment(javaHome, selectedEnvironment, platform),
|
|
271
279
|
...ghidraHeadlessJavaOptions(paths.homeRoot, paths.tempRoot, platform),
|
|
272
280
|
HOME: paths.homeRoot,
|
|
273
281
|
TMPDIR: paths.tempRoot,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
1
2
|
import {} from "../application/AnalysisProvider.js";
|
|
2
3
|
import { createAnalysisProfile, } from "../domain/analysisProfile.js";
|
|
3
4
|
import { jsonObjectSchema, jsonValueSchema, } from "../domain/jsonValue.js";
|
|
@@ -9,7 +10,6 @@ import { resolveGhidraExtensions } from "./extensions/GhidraExtensions.js";
|
|
|
9
10
|
import { CAPABILITIES, windowsP0Capabilities, GHIDRA_PROVIDER_IDENTITY, GHIDRA_OPERATIONS, } from "./GhidraProviderCapabilities.js";
|
|
10
11
|
import { createGhidraProviderClient, } from "./GhidraProviderClient.js";
|
|
11
12
|
import { windowsNativeAuthorityUnavailableReason, hasWindowsNativeAuthority, windowsNativeCapabilities, } from "../process/WindowsAuthority.js";
|
|
12
|
-
export { GHIDRA_PROVIDER_IDENTITY, GHIDRA_OPERATIONS };
|
|
13
13
|
const SUPPORTED_ARCHITECTURES = new Set(["x86", "x86_64", "arm", "arm64"]);
|
|
14
14
|
/** Ghidra candidate backed by an isolated ephemeral headless import. */
|
|
15
15
|
export class GhidraProvider {
|
|
@@ -18,11 +18,13 @@ export class GhidraProvider {
|
|
|
18
18
|
installationHost;
|
|
19
19
|
clientFactory;
|
|
20
20
|
#installation;
|
|
21
|
-
|
|
21
|
+
environment;
|
|
22
|
+
constructor(config, logger, environment, installationHost, clientFactory = (options) => new GhidraClient(options)) {
|
|
22
23
|
this.config = config;
|
|
23
24
|
this.logger = logger;
|
|
24
25
|
this.installationHost = installationHost;
|
|
25
26
|
this.clientFactory = clientFactory;
|
|
27
|
+
this.environment = snapshotEnvironment(environment, installationHost?.platform);
|
|
26
28
|
}
|
|
27
29
|
identity() {
|
|
28
30
|
return GHIDRA_PROVIDER_IDENTITY;
|
|
@@ -125,6 +127,7 @@ export class GhidraProvider {
|
|
|
125
127
|
createClient(target, profile, context) {
|
|
126
128
|
return createGhidraProviderClient({
|
|
127
129
|
config: this.config,
|
|
130
|
+
environment: this.environment,
|
|
128
131
|
logger: this.logger,
|
|
129
132
|
clientFactory: this.clientFactory,
|
|
130
133
|
target,
|
|
@@ -135,6 +138,7 @@ export class GhidraProvider {
|
|
|
135
138
|
}
|
|
136
139
|
#inspectInstallation() {
|
|
137
140
|
const options = {
|
|
141
|
+
environment: this.environment,
|
|
138
142
|
...(this.config.ghidraInstallDir === undefined
|
|
139
143
|
? {}
|
|
140
144
|
: { installDir: this.config.ghidraInstallDir }),
|
|
@@ -146,6 +146,12 @@ export const CAPABILITIES = Object.freeze(GHIDRA_OPERATIONS.map((operation) => {
|
|
|
146
146
|
operation,
|
|
147
147
|
available: true,
|
|
148
148
|
reason: null,
|
|
149
|
+
// Project writes are private import machinery. Analysis reads are bound
|
|
150
|
+
// to the artifact/profile; session annotations disable snapshot replay.
|
|
151
|
+
...(operation === "annotate_native_function" ||
|
|
152
|
+
operation === "list_documents"
|
|
153
|
+
? {}
|
|
154
|
+
: { cachePolicy: "snapshot" }),
|
|
149
155
|
effects: Object.freeze({
|
|
150
156
|
mutatesArtifact: operation === "annotate_native_function",
|
|
151
157
|
launchesProcess: true,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { analysisErrorWithCleanupFailure } from "../application/binary/AnalysisClientCleanup.js";
|
|
1
2
|
import { fileURLToPath } from "node:url";
|
|
2
3
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
3
4
|
import { AnalysisCancelledError, AnalysisArtifactChangedError, AnalysisAccessDeniedError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisResourceConstraintError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
|
|
@@ -57,6 +58,7 @@ export const createGhidraProviderClient = (input) => {
|
|
|
57
58
|
startupTimeoutMs: config.ghidraStartupTimeoutMs,
|
|
58
59
|
platform: installation.platform,
|
|
59
60
|
launcher: new GhidraHeadlessLauncher({
|
|
61
|
+
environment: input.environment,
|
|
60
62
|
analyzeHeadlessPath: prerequisites.value.analyzeHeadlessPath,
|
|
61
63
|
javaHome: prerequisites.value.javaHome,
|
|
62
64
|
bridgeScriptPath: fileURLToPath(new URL("../../bridge/ghidra/ReaGhidraBridge.java", import.meta.url)),
|
|
@@ -87,8 +89,10 @@ export const createGhidraProviderClient = (input) => {
|
|
|
87
89
|
extensionFailure = ghidraExtensionFailure(extensions, info.analysis_extensions ?? [], operation);
|
|
88
90
|
if (extensionFailure === undefined)
|
|
89
91
|
return undefined;
|
|
90
|
-
await client.close();
|
|
91
|
-
return
|
|
92
|
+
const closed = await client.close();
|
|
93
|
+
return closed.ok
|
|
94
|
+
? extensionFailure
|
|
95
|
+
: analysisErrorWithCleanupFailure(extensionFailure, closed.error, operation);
|
|
92
96
|
};
|
|
93
97
|
const releaseLimitation = unverifiedGhidraBuildLimitation(prerequisites.value.providerVersion);
|
|
94
98
|
const sessionLimitations = [
|
|
@@ -181,9 +185,15 @@ const ghidraClientPrerequisites = (target, profile, installation) => {
|
|
|
181
185
|
};
|
|
182
186
|
const unavailableClient = (failure) => ({
|
|
183
187
|
execute: () => Promise.resolve(err(failure)),
|
|
184
|
-
close: () => Promise.resolve(),
|
|
188
|
+
close: () => Promise.resolve(ok(null)),
|
|
185
189
|
});
|
|
186
190
|
const projectSessionError = (operation, failure, startupTimeoutMs) => {
|
|
191
|
+
const primary = projectPrimarySessionError(operation, failure, startupTimeoutMs);
|
|
192
|
+
return failure.cleanupFailure === undefined
|
|
193
|
+
? primary
|
|
194
|
+
: analysisErrorWithCleanupFailure(primary, failure.cleanupFailure, operation);
|
|
195
|
+
};
|
|
196
|
+
const projectPrimarySessionError = (operation, failure, startupTimeoutMs) => {
|
|
187
197
|
if (failure.cause instanceof AnalysisAccessDeniedError)
|
|
188
198
|
return new AnalysisAccessDeniedError(operation, failure.cause.path, failure.cause.systemCode, { cause: failure });
|
|
189
199
|
if (failure.cause instanceof AnalysisArtifactChangedError)
|
|
@@ -4,6 +4,7 @@ export class GhidraSessionError extends Error {
|
|
|
4
4
|
diagnostics;
|
|
5
5
|
timeoutMs;
|
|
6
6
|
remoteCode;
|
|
7
|
+
cleanupFailure;
|
|
7
8
|
constructor(kind, message, diagnostics = {}, options = {}) {
|
|
8
9
|
super(message, options);
|
|
9
10
|
this.kind = kind;
|
|
@@ -11,6 +12,7 @@ export class GhidraSessionError extends Error {
|
|
|
11
12
|
this.diagnostics = structuredClone(diagnostics);
|
|
12
13
|
this.timeoutMs = options.timeoutMs;
|
|
13
14
|
this.remoteCode = options.remoteCode;
|
|
15
|
+
this.cleanupFailure = options.cleanupFailure;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
/** Build a session failure while preserving bounded remote failure metadata. */
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { dirname, isAbsolute, resolve, sep } from "node:path";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
/** Session roots may not contain a dot-prefixed path element. */
|
|
4
|
+
const hasDotPrefixElement = (directory) => resolve(directory)
|
|
5
|
+
.split(sep)
|
|
6
|
+
.some((element) => element.startsWith("."));
|
|
7
|
+
/** Nearest ancestor of `directory`, inclusive, that has no dot-prefixed element. */
|
|
8
|
+
const nearestSafeAncestor = (directory) => {
|
|
9
|
+
let current = resolve(directory);
|
|
10
|
+
for (;;) {
|
|
11
|
+
if (!hasDotPrefixElement(current))
|
|
12
|
+
return current;
|
|
13
|
+
const parent = dirname(current);
|
|
14
|
+
if (parent === current)
|
|
15
|
+
return undefined;
|
|
16
|
+
current = parent;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Select a session root usable as the parent of a Ghidra project path.
|
|
21
|
+
*
|
|
22
|
+
* Ghidra validates every project path element with `NamingUtilities.checkName`
|
|
23
|
+
* and aborts the headless analyzer on any element that starts with `.`, so an
|
|
24
|
+
* inherited `TMPDIR` such as `~/.cache/<tool>` fails every Ghidra operation
|
|
25
|
+
* with a generic analysis failure. Prefer the inherited base when it is usable,
|
|
26
|
+
* then a dot-free platform temp directory, then the nearest dot-free ancestor.
|
|
27
|
+
*/
|
|
28
|
+
export const ghidraSessionRoot = (options = {}) => {
|
|
29
|
+
const base = resolve(options.base ?? tmpdir());
|
|
30
|
+
if (!hasDotPrefixElement(base))
|
|
31
|
+
return base;
|
|
32
|
+
const platform = options.platform ?? process.platform;
|
|
33
|
+
const fallback = options.fallback ?? (platform === "win32" ? undefined : "/tmp");
|
|
34
|
+
if (fallback !== undefined &&
|
|
35
|
+
isAbsolute(fallback) &&
|
|
36
|
+
!hasDotPrefixElement(fallback))
|
|
37
|
+
return resolve(fallback);
|
|
38
|
+
return nearestSafeAncestor(base) ?? base;
|
|
39
|
+
};
|