rea-agents 6.3.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +51 -19
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +22 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +70 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +66 -31
- package/dist/application/DirectAnalysis.js +2 -2
- package/dist/application/DirectAnalysisCleanup.js +1 -1
- package/dist/application/DirectAnalysisStatus.js +1 -1
- package/dist/application/Doctor.js +5 -3
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +6 -0
- package/dist/application/JsonFiles.js +6 -5
- package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
- package/dist/application/LinuxHopper.js +4 -12
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +9 -3
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +93 -7
- package/dist/application/Setup.js +54 -6
- package/dist/application/SetupClientConfiguration.js +116 -16
- package/dist/application/SetupHost.js +102 -24
- package/dist/application/SetupPlan.js +5 -8
- package/dist/application/SetupSkill.js +58 -39
- package/dist/application/SupportedClients.js +290 -65
- package/dist/application/Uninstall.js +158 -10
- package/dist/application/UpdateMaintenance.js +17 -21
- package/dist/application/Utf8JsonInput.js +7 -0
- package/dist/application/WebScriptExportService.js +131 -65
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/BinarySession.js +2 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
- package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +20 -15
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +176 -102
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
- package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +75 -32
- package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +62 -25
- package/dist/artifacts/inventory/scanReader.js +38 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +5 -0
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +32 -10
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
- package/dist/browser/PlaywrightScenarioSession.js +127 -54
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +3 -3
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreBinaryCommands.js +0 -5
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +6 -1
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +17 -1
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +11 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/utilityCommands.js +66 -18
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +6 -0
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +2 -2
- package/dist/cliObservationOptions.js +3 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/directAnalysis.js +12 -4
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +10 -10
- package/dist/contracts/javascript/electronToolContracts.js +15 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionToolContracts.js +2 -2
- package/dist/contracts/sessionToolSchemas.js +6 -2
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -3
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -6
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +2 -1
- package/dist/domain/analysisView/analysisView.js +52 -2
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +2 -2
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +35 -7
- package/dist/domain/artifactGraph.js +5 -3
- package/dist/domain/artifactIdentity.js +30 -2
- package/dist/domain/artifactInspection.js +3 -43
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +11 -12
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/evidence.js +2 -1
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
- package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
- package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
- package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
- package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
- package/dist/domain/javascript/javascriptAstValues.js +32 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
- package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
- package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
- package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonShape.js +63 -52
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/managed/managedApplicationGraph.js +37 -0
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +91 -1
- package/dist/domain/process/processCaptureExample.js +24 -0
- package/dist/domain/process/processCaptureValidation.js +79 -0
- package/dist/domain/process/processScenario.js +59 -7
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/referenceSourceGraph.js +25 -16
- package/dist/domain/referenceSourceImportParsing.js +6 -3
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/webBundleAnalyzerInspection.js +14 -2
- package/dist/domain/webCaptureDiff.js +102 -4
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +55 -24
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +33 -1
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +76 -4
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +1 -1
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +80 -39
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +8 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +3 -1
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/NativeMacOSProvider.js +91 -16
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +96 -39
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +28 -4
- package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessHarness.js +194 -26
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +97 -25
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +32 -3
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +49 -18
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +33 -5
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
|
@@ -65,7 +65,7 @@ const hostCheck = async (host) => {
|
|
|
65
65
|
? `${host.platform} ${host.architecture}`
|
|
66
66
|
: `${linuxDistribution.id} ${linuxDistribution.versionId ?? "unknown"}`);
|
|
67
67
|
return check("host", supported, detail, {
|
|
68
|
-
remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, and the experimental Windows x64 Ghidra P0 boundary.",
|
|
68
|
+
remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, Omarchy, and the experimental Windows x64 Ghidra P0 boundary.",
|
|
69
69
|
classification: "unsupported_host",
|
|
70
70
|
});
|
|
71
71
|
};
|
|
@@ -3,22 +3,17 @@ import {} from "../domain/analysisErrorBase.js";
|
|
|
3
3
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
5
|
import { compareBundles } from "../domain/bundleComparison.js";
|
|
6
|
-
import { EvidenceLedger } from "./investigation/EvidenceLedger.js";
|
|
7
6
|
import { readEvidenceBundle, writeEvidenceBundle, } from "./EvidenceBundleFiles.js";
|
|
8
|
-
/** Validate
|
|
7
|
+
/** Validate a standalone bundle and report its complete record/revision counts. */
|
|
9
8
|
export const importEvidenceBundleCommand = async (path) => {
|
|
10
9
|
const loaded = await readEvidenceBundle(path);
|
|
11
10
|
if (!loaded.ok)
|
|
12
11
|
return loaded;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
unknowns_added: imported.value.unknownsAdded,
|
|
19
|
-
total: ledger.export().records.length,
|
|
20
|
-
})
|
|
21
|
-
: imported;
|
|
12
|
+
return ok({
|
|
13
|
+
imported: loaded.value.records.length,
|
|
14
|
+
unknowns_added: loaded.value.unknowns.length,
|
|
15
|
+
total: loaded.value.records.length,
|
|
16
|
+
});
|
|
22
17
|
};
|
|
23
18
|
/** Validate a source bundle and atomically export canonical bytes. */
|
|
24
19
|
export const exportEvidenceBundleCommand = async (sourcePath, outputPath, overwrite) => {
|
|
@@ -46,7 +41,6 @@ export const compareEvidenceBundlesCommand = async (input) => {
|
|
|
46
41
|
}));
|
|
47
42
|
}
|
|
48
43
|
};
|
|
49
|
-
const createLedger = () => new EvidenceLedger();
|
|
50
44
|
const projectWrite = (bundle, written) => written.ok
|
|
51
45
|
? ok({
|
|
52
46
|
path: written.value.path,
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { stripComments } from "jsonc-parser";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { err, ok } from "../domain/result.js";
|
|
6
|
+
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
7
|
+
import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
8
|
+
import { clientConfigurationValuesEqual, clientRegistrationEntry, geminiServerPolicyBlock, parseGeminiMcpPolicy, } from "./ClientConfigurationDocument.js";
|
|
9
|
+
import { readConfigurationFile, readConfigurationText, } from "./ClientConfigurationFiles.js";
|
|
10
|
+
const folderTrustSchema = z
|
|
11
|
+
.object({
|
|
12
|
+
security: z
|
|
13
|
+
.object({
|
|
14
|
+
folderTrust: z
|
|
15
|
+
.object({ enabled: z.boolean().optional() })
|
|
16
|
+
.passthrough()
|
|
17
|
+
.optional(),
|
|
18
|
+
})
|
|
19
|
+
.passthrough()
|
|
20
|
+
.optional(),
|
|
21
|
+
})
|
|
22
|
+
.passthrough();
|
|
23
|
+
const trustRulesSchema = z.record(z.string(), z.enum(["TRUST_FOLDER", "TRUST_PARENT", "DO_NOT_TRUST"]));
|
|
24
|
+
const sourceFailure = (path, cause) => ({
|
|
25
|
+
kind: "malformed",
|
|
26
|
+
path,
|
|
27
|
+
detail: `Gemini settings in ${path} are malformed: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
28
|
+
});
|
|
29
|
+
// Gemini resolves symlinks when possible and compares macOS/Windows paths without case.
|
|
30
|
+
const normalizedPath = async (path, platform) => {
|
|
31
|
+
const physical = await realpath(path).catch(() => path);
|
|
32
|
+
const absolute = resolve(physical).replaceAll("\\", "/");
|
|
33
|
+
return platform === "win32" || platform === "darwin"
|
|
34
|
+
? absolute.toLowerCase()
|
|
35
|
+
: absolute;
|
|
36
|
+
};
|
|
37
|
+
const workspaceTrusted = async (settings, sources) => {
|
|
38
|
+
let enabled = true;
|
|
39
|
+
for (const { path, document } of sources) {
|
|
40
|
+
const parsed = folderTrustSchema.safeParse(document.document);
|
|
41
|
+
if (!parsed.success)
|
|
42
|
+
return err(sourceFailure(path, parsed.error));
|
|
43
|
+
enabled = parsed.data.security?.folderTrust?.enabled ?? enabled;
|
|
44
|
+
}
|
|
45
|
+
if (settings.trustOverride !== undefined)
|
|
46
|
+
return ok(settings.trustOverride);
|
|
47
|
+
if (!enabled)
|
|
48
|
+
return ok(true);
|
|
49
|
+
const text = await readConfigurationText(settings.trustedFoldersPath);
|
|
50
|
+
if (!text.ok)
|
|
51
|
+
return text;
|
|
52
|
+
if (text.value === undefined)
|
|
53
|
+
return ok(false);
|
|
54
|
+
let rules;
|
|
55
|
+
try {
|
|
56
|
+
// Gemini strips comments, but rejects trailing commas, BOMs and invalid trust levels.
|
|
57
|
+
rules = trustRulesSchema.parse(JSON.parse(stripComments(text.value)));
|
|
58
|
+
}
|
|
59
|
+
catch (cause) {
|
|
60
|
+
return err(sourceFailure(settings.trustedFoldersPath, cause));
|
|
61
|
+
}
|
|
62
|
+
const workspace = await normalizedPath(settings.workspaceDirectory, settings.platform);
|
|
63
|
+
let longest = -1;
|
|
64
|
+
let trusted = false;
|
|
65
|
+
for (const [path, level] of Object.entries(rules)) {
|
|
66
|
+
const effective = await normalizedPath(level === "TRUST_PARENT" ? dirname(path) : path, settings.platform);
|
|
67
|
+
if ((workspace === effective ||
|
|
68
|
+
workspace.startsWith(effective.endsWith("/") ? effective : `${effective}/`)) &&
|
|
69
|
+
path.length > longest) {
|
|
70
|
+
longest = path.length;
|
|
71
|
+
trusted = level !== "DO_NOT_TRUST";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return ok(trusted);
|
|
75
|
+
};
|
|
76
|
+
/** Check effective Gemini scopes while preserving their authority and source identity. */
|
|
77
|
+
export const readClientPolicyBlock = async (client, userDocument, desiredRegistration) => {
|
|
78
|
+
if (client.name !== "gemini_cli" || client.geminiSettings === undefined)
|
|
79
|
+
return ok(undefined);
|
|
80
|
+
const settings = client.geminiSettings;
|
|
81
|
+
const sources = [];
|
|
82
|
+
const higher = [];
|
|
83
|
+
for (const path of [
|
|
84
|
+
settings.defaultsPath,
|
|
85
|
+
client.configPath,
|
|
86
|
+
settings.systemPath,
|
|
87
|
+
]) {
|
|
88
|
+
const parsed = path === client.configPath && userDocument !== undefined
|
|
89
|
+
? ok(userDocument)
|
|
90
|
+
: await readConfigurationFile(path, "json");
|
|
91
|
+
if (!parsed.ok)
|
|
92
|
+
return parsed;
|
|
93
|
+
if (parsed.value !== undefined)
|
|
94
|
+
sources.push({ path, document: parsed.value });
|
|
95
|
+
}
|
|
96
|
+
const workspace = await normalizedPath(settings.workspaceDirectory, settings.platform);
|
|
97
|
+
const home = await normalizedPath(dirname(dirname(client.configPath)), settings.platform);
|
|
98
|
+
if (workspace !== home) {
|
|
99
|
+
const path = resolve(settings.workspaceDirectory, ".gemini", "settings.json");
|
|
100
|
+
const document = await readConfigurationFile(path, "json");
|
|
101
|
+
if (!document.ok)
|
|
102
|
+
return document;
|
|
103
|
+
if (document.value !== undefined) {
|
|
104
|
+
const trusted = await workspaceTrusted(settings, sources);
|
|
105
|
+
if (!trusted.ok)
|
|
106
|
+
return trusted;
|
|
107
|
+
if (trusted.value) {
|
|
108
|
+
const source = { path, document: document.value };
|
|
109
|
+
const systemIndex = sources.findIndex((item) => item.path === settings.systemPath);
|
|
110
|
+
sources.splice(systemIndex < 0 ? sources.length : systemIndex, 0, source);
|
|
111
|
+
higher.push(source);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const system = sources.find(({ path }) => path === settings.systemPath);
|
|
116
|
+
if (system !== undefined)
|
|
117
|
+
higher.push(system);
|
|
118
|
+
const policies = [];
|
|
119
|
+
for (const { path, document } of sources) {
|
|
120
|
+
try {
|
|
121
|
+
policies.push(parseGeminiMcpPolicy(document));
|
|
122
|
+
}
|
|
123
|
+
catch (cause) {
|
|
124
|
+
return err(sourceFailure(path, cause));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const policy = geminiServerPolicyBlock(policies, PRODUCT_IDENTITY.mcpServerKey);
|
|
128
|
+
if (policy !== undefined)
|
|
129
|
+
return ok(`${policy} Settings sources: ${sources.map(({ path }) => path).join(", ")}.`);
|
|
130
|
+
// mcpServers uses shallow merge: the entire same-name definition is replaced.
|
|
131
|
+
const override = higher.findLast(({ document }) => Object.hasOwn(document.servers, PRODUCT_IDENTITY.mcpServerKey));
|
|
132
|
+
const desired = desiredRegistration ??
|
|
133
|
+
userDocument?.servers[PRODUCT_IDENTITY.mcpServerKey] ??
|
|
134
|
+
clientRegistrationEntry("json", npxRegistrationCommand(), {});
|
|
135
|
+
if (override !== undefined &&
|
|
136
|
+
!clientConfigurationValuesEqual(override.document.servers[PRODUCT_IDENTITY.mcpServerKey], desired))
|
|
137
|
+
return ok(`Gemini mcpServers.${PRODUCT_IDENTITY.mcpServerKey} in ${override.path} overrides the user registration. Review that settings file before rerunning setup; REA does not modify system or workspace settings.`);
|
|
138
|
+
return ok(undefined);
|
|
139
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from "node:path";
|
|
3
|
+
/** An unresolved Hermes profile must not be configured as the default home. */
|
|
4
|
+
export class HermesClientPathError extends Error {
|
|
5
|
+
path;
|
|
6
|
+
constructor(path, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.path = path;
|
|
9
|
+
this.name = "HermesClientPathError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const defaultDirectory = (home, platform, env) => {
|
|
13
|
+
const suffix = env.HERMES_DATA_DIR_SUFFIX ?? "";
|
|
14
|
+
return platform === "win32"
|
|
15
|
+
? join(env.LOCALAPPDATA?.trim() || join(home, "AppData", "Local"), `hermes${suffix}`)
|
|
16
|
+
: join(home, `.hermes${suffix}`);
|
|
17
|
+
};
|
|
18
|
+
const expandedDirectory = (home, platform, env) => {
|
|
19
|
+
const override = env.HERMES_HOME?.trim();
|
|
20
|
+
if (!override)
|
|
21
|
+
return undefined;
|
|
22
|
+
const variables = override.replace(/\$(\w+|\{[^}]*\})/gu, (match, variable) => {
|
|
23
|
+
const key = variable.startsWith("{") ? variable.slice(1, -1) : variable;
|
|
24
|
+
return env[key] ?? match;
|
|
25
|
+
});
|
|
26
|
+
const expanded = platform === "win32"
|
|
27
|
+
? variables.replace(/%([^%]+)%/gu, (match, variable) => env[variable] ?? match)
|
|
28
|
+
: variables;
|
|
29
|
+
if (expanded === "~")
|
|
30
|
+
return home;
|
|
31
|
+
if (expanded.startsWith("~/") ||
|
|
32
|
+
(platform === "win32" && expanded.startsWith("~\\")))
|
|
33
|
+
return join(home, expanded.slice(2));
|
|
34
|
+
return resolve(expanded);
|
|
35
|
+
};
|
|
36
|
+
const physicalPath = (path) => {
|
|
37
|
+
try {
|
|
38
|
+
return realpathSync(path);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return resolve(path);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const within = (root, path) => {
|
|
45
|
+
const difference = relative(physicalPath(root), physicalPath(path));
|
|
46
|
+
return (difference === "" ||
|
|
47
|
+
(!isAbsolute(difference) &&
|
|
48
|
+
difference !== ".." &&
|
|
49
|
+
!difference.startsWith(`..${sep}`)));
|
|
50
|
+
};
|
|
51
|
+
const PROFILE_MARKERS = [
|
|
52
|
+
"config.yaml",
|
|
53
|
+
".env",
|
|
54
|
+
"SOUL.md",
|
|
55
|
+
"profile.yaml",
|
|
56
|
+
"auth.json",
|
|
57
|
+
"state.db",
|
|
58
|
+
];
|
|
59
|
+
const RESERVED_PROFILES = new Set(["hermes", "test", "tmp", "root", "sudo"]);
|
|
60
|
+
const liveProfile = (path) => {
|
|
61
|
+
try {
|
|
62
|
+
if (!statSync(path).isDirectory())
|
|
63
|
+
return false;
|
|
64
|
+
try {
|
|
65
|
+
statSync(join(dirname(path), ".deleted", basename(path)));
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* No tombstone. */
|
|
70
|
+
}
|
|
71
|
+
return PROFILE_MARKERS.some((marker) => {
|
|
72
|
+
try {
|
|
73
|
+
const status = lstatSync(join(path, marker));
|
|
74
|
+
return status.isFile() || status.isSymbolicLink();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
/** Match Hermes CLI sticky-profile selection while retaining the configured path spelling. */
|
|
86
|
+
export const resolveHermesClientHome = (home, platform, env) => {
|
|
87
|
+
const native = defaultDirectory(home, platform, env);
|
|
88
|
+
const root = expandedDirectory(home, platform, env) ?? native;
|
|
89
|
+
// An explicit named profile bypasses the root's sticky selection in Hermes CLI.
|
|
90
|
+
if (basename(dirname(root)) === "profiles")
|
|
91
|
+
return root;
|
|
92
|
+
const stickyRoot = within(native, root) ? native : root;
|
|
93
|
+
let name;
|
|
94
|
+
try {
|
|
95
|
+
// Python uses utf-8-sig and ignores unreadable / invalid-UTF8 active_profile files.
|
|
96
|
+
name = new TextDecoder("utf-8", { fatal: true })
|
|
97
|
+
.decode(readFileSync(join(stickyRoot, "active_profile")))
|
|
98
|
+
.trim();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return root;
|
|
102
|
+
}
|
|
103
|
+
if (name === "" || name === "default")
|
|
104
|
+
return root;
|
|
105
|
+
const canonical = name.toLowerCase();
|
|
106
|
+
if (canonical === "default")
|
|
107
|
+
return root;
|
|
108
|
+
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/u.test(canonical) ||
|
|
109
|
+
RESERVED_PROFILES.has(canonical))
|
|
110
|
+
throw new HermesClientPathError(join(stickyRoot, "active_profile"), `Invalid saved Hermes profile ${JSON.stringify(name)}. Run 'hermes profile use default' or repair active_profile.`);
|
|
111
|
+
const selected = join(root, "profiles", canonical);
|
|
112
|
+
if (!liveProfile(selected))
|
|
113
|
+
throw new HermesClientPathError(selected, `Saved Hermes profile ${JSON.stringify(name)} is missing, deleted, or has no profile identity. Run 'hermes profile use default' or restore that profile before configuring it.`);
|
|
114
|
+
return selected;
|
|
115
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Maximum admitted vendor response bytes, shared by Hopper setup adapters. */
|
|
2
|
+
export const HOPPER_DOWNLOAD_BYTES = 100_000_000;
|
|
3
|
+
/** Bound observed response bytes before retaining them, including chunked bodies. */
|
|
4
|
+
export const downloadHopperPackage = async (url, options = {}) => {
|
|
5
|
+
const deadline = AbortSignal.timeout(120_000);
|
|
6
|
+
const response = await fetch(url, {
|
|
7
|
+
headers: { accept: "application/json", "user-agent": "rea-installer" },
|
|
8
|
+
signal: options.signal === undefined
|
|
9
|
+
? deadline
|
|
10
|
+
: AbortSignal.any([options.signal, deadline]),
|
|
11
|
+
});
|
|
12
|
+
const refused = { ok: false, bytes: new Uint8Array() };
|
|
13
|
+
if (!response.ok ||
|
|
14
|
+
Number(response.headers.get("content-length")) > HOPPER_DOWNLOAD_BYTES) {
|
|
15
|
+
await response.body?.cancel();
|
|
16
|
+
return refused;
|
|
17
|
+
}
|
|
18
|
+
if (response.body === null)
|
|
19
|
+
return { ok: true, bytes: new Uint8Array() };
|
|
20
|
+
const reader = response.body.getReader();
|
|
21
|
+
const chunks = [];
|
|
22
|
+
let bytes = 0;
|
|
23
|
+
try {
|
|
24
|
+
while (true) {
|
|
25
|
+
const chunk = await reader.read();
|
|
26
|
+
if (chunk.done)
|
|
27
|
+
return { ok: true, bytes: Buffer.concat(chunks, bytes) };
|
|
28
|
+
if (chunk.value.byteLength > HOPPER_DOWNLOAD_BYTES - bytes) {
|
|
29
|
+
await reader.cancel();
|
|
30
|
+
return refused;
|
|
31
|
+
}
|
|
32
|
+
chunks.push(chunk.value);
|
|
33
|
+
bytes += chunk.value.byteLength;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
reader.releaseLock();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -24,6 +24,12 @@ export const MANAGED_STATIC_PROVIDER = Object.freeze({
|
|
|
24
24
|
name: "REA managed static analysis provider",
|
|
25
25
|
version: "1",
|
|
26
26
|
});
|
|
27
|
+
/** Provider identity for portable, execution-free PE resource decoding. */
|
|
28
|
+
export const PE_RESOURCES_PROVIDER = Object.freeze({
|
|
29
|
+
id: "rea-pe-resources",
|
|
30
|
+
name: "REA PE resource parser",
|
|
31
|
+
version: "1",
|
|
32
|
+
});
|
|
27
33
|
/** Provider identity for deterministic managed-code comparison workflows. */
|
|
28
34
|
export const MANAGED_WORKFLOW_PROVIDER = {
|
|
29
35
|
id: "rea-dotnet-workflows",
|
|
@@ -3,18 +3,19 @@ import { basename, dirname, resolve } from "node:path";
|
|
|
3
3
|
import { EvidenceFileError } from "../domain/evidenceErrors.js";
|
|
4
4
|
import { AnalysisCancelledError, AnalysisResourceConstraintError, } from "../domain/analysisErrorCore.js";
|
|
5
5
|
import { err, ok } from "../domain/result.js";
|
|
6
|
-
import {
|
|
7
|
-
import { readRegularFile } from "./RegularFileRead.js";
|
|
6
|
+
import { readJsonInputFile } from "./JsonInputFile.js";
|
|
8
7
|
import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
|
|
9
8
|
/** Read JSON data from a regular file at the caller-supplied path. */
|
|
10
9
|
export const readJsonFile = async (path) => {
|
|
11
10
|
const requestedPath = resolve(path);
|
|
12
11
|
try {
|
|
13
|
-
const
|
|
14
|
-
const decoded = parseUtf8Json(encoded, "read_evidence_file", requestedPath);
|
|
12
|
+
const decoded = await readJsonInputFile(requestedPath, "read_evidence_file");
|
|
15
13
|
if (!decoded.ok) {
|
|
14
|
+
if (decoded.error instanceof AnalysisResourceConstraintError)
|
|
15
|
+
return err(decoded.error);
|
|
16
16
|
return err(new EvidenceFileError("read", "invalid-json", {
|
|
17
|
-
cause: decoded.cause
|
|
17
|
+
cause: decoded.error.cause ??
|
|
18
|
+
new SyntaxError(decoded.error.issues[0]?.message ?? decoded.error.message),
|
|
18
19
|
path: requestedPath,
|
|
19
20
|
}));
|
|
20
21
|
}
|
|
@@ -3,35 +3,46 @@ import { pipeline } from "node:stream/promises";
|
|
|
3
3
|
import { getHeapStatistics } from "node:v8";
|
|
4
4
|
import parser from "stream-json/parser.js";
|
|
5
5
|
import streamValues from "stream-json/streamers/stream-values.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { RegularFileChangedError } from "../filesystem/RegularFile.js";
|
|
7
|
+
import { withRegularFile } from "./RegularFileRead.js";
|
|
8
|
+
import { JSON_BYTE_ORDER_MARK_MESSAGE, JSON_INPUT_RESOURCE_REMEDIATION, parseUtf8Json, } from "./Utf8JsonInput.js";
|
|
9
|
+
import { AnalysisInputError, AnalysisResourceConstraintError, } from "../domain/analysisErrorCore.js";
|
|
10
|
+
import { err, ok } from "../domain/result.js";
|
|
10
11
|
const READ_CHUNK_BYTES = 64 * 1024;
|
|
11
|
-
const
|
|
12
|
+
const PACKED_TOKEN_PART_CODE_UNITS = 64 * 1024;
|
|
12
13
|
// Retain native-parser speed for modest inputs while bounding its extra copies.
|
|
13
14
|
// This selects an implementation; larger files remain accepted through streaming.
|
|
14
15
|
const NATIVE_PARSE_READ_BUDGET = 8 * 1024 * 1024;
|
|
16
|
+
/** Keep native parsing only when input copies and value expansion fit live headroom. */
|
|
17
|
+
const nativeParseFits = (inputBytes) => inputBytes <= NATIVE_PARSE_READ_BUDGET &&
|
|
18
|
+
// The assembler estimate reserves up to 128 bytes per two-byte container.
|
|
19
|
+
// Allow that 64x expansion plus byte/text copies before native JSON.parse,
|
|
20
|
+
// whose individual container allocations cannot be intercepted.
|
|
21
|
+
inputBytes * 72 + READ_CHUNK_BYTES <=
|
|
22
|
+
getHeapStatistics().total_available_size;
|
|
15
23
|
/** Parse strict UTF-8 JSON without requiring a whole-document string. */
|
|
16
|
-
export const
|
|
24
|
+
export const readJsonInputFile = (path, operation, signal) => withRegularFile(path, async (handle, stats) => {
|
|
17
25
|
let found = false;
|
|
18
26
|
let value;
|
|
19
27
|
try {
|
|
20
|
-
const prefix = stats.size
|
|
28
|
+
const prefix = nativeParseFits(stats.size)
|
|
21
29
|
? await readPrefix(handle, stats.size + 1, signal)
|
|
22
30
|
: undefined;
|
|
23
|
-
if (prefix
|
|
24
|
-
|
|
31
|
+
if (prefix !== undefined) {
|
|
32
|
+
if (!prefix.complete || prefix.bytes.length !== stats.size)
|
|
33
|
+
throw new RegularFileChangedError(path);
|
|
34
|
+
const parsed = parseUtf8Json(prefix.bytes, operation, path, "json-file-input");
|
|
25
35
|
return parsed.ok
|
|
26
36
|
? ok(parsed.value)
|
|
27
37
|
: err(invalidJson(operation, parsed.error, parsed.cause));
|
|
28
38
|
}
|
|
29
|
-
await pipeline(decodedChunks(handle,
|
|
39
|
+
await pipeline(decodedChunks(handle, stats.size, path, signal), parser.asStream({
|
|
30
40
|
jsonStreaming: false,
|
|
31
41
|
streamValues: false,
|
|
32
42
|
packKeys: false,
|
|
33
43
|
packStrings: false,
|
|
34
|
-
|
|
44
|
+
packNumbers: false,
|
|
45
|
+
}), packJsonScalars(operation, stats.size, path), admitJsonAssembly(operation, stats.size, path), streamValues.asStream(), async (rows) => {
|
|
35
46
|
for await (const row of rows) {
|
|
36
47
|
if (found ||
|
|
37
48
|
typeof row !== "object" ||
|
|
@@ -62,7 +73,8 @@ export const readCliJsonFile = (path, operation, signal) => withRegularFile(path
|
|
|
62
73
|
((cause instanceof RangeError &&
|
|
63
74
|
cause.message === "Invalid string length") ||
|
|
64
75
|
("code" in cause && cause.code === "ERR_STRING_TOO_LONG")))
|
|
65
|
-
return err(new AnalysisResourceConstraintError(operation, "memory", "An individual JSON string exceeds the runtime string limit", {
|
|
76
|
+
return err(new AnalysisResourceConstraintError(operation, "memory", "An individual JSON string or number token exceeds the runtime string limit", {
|
|
77
|
+
input_path: path,
|
|
66
78
|
input_file_bytes: stats.size,
|
|
67
79
|
max_string_code_units: constants.MAX_STRING_LENGTH,
|
|
68
80
|
}, {
|
|
@@ -71,8 +83,8 @@ export const readCliJsonFile = (path, operation, signal) => withRegularFile(path
|
|
|
71
83
|
}));
|
|
72
84
|
throw cause;
|
|
73
85
|
}
|
|
74
|
-
}, signal);
|
|
75
|
-
const
|
|
86
|
+
}, { signal });
|
|
87
|
+
const packJsonScalars = (operation, inputFileBytes, path) => async function* (tokens) {
|
|
76
88
|
let kind;
|
|
77
89
|
let length = 0;
|
|
78
90
|
let value = "";
|
|
@@ -86,21 +98,25 @@ const packJsonStrings = (operation, inputFileBytes) => async function* (tokens)
|
|
|
86
98
|
case "startString":
|
|
87
99
|
kind = token.name === "startKey" ? "keyValue" : "stringValue";
|
|
88
100
|
break;
|
|
101
|
+
case "startNumber":
|
|
102
|
+
kind = "numberValue";
|
|
103
|
+
break;
|
|
104
|
+
case "numberChunk":
|
|
89
105
|
case "stringChunk":
|
|
90
106
|
if (kind === undefined ||
|
|
91
107
|
!("value" in token) ||
|
|
92
108
|
typeof token.value !== "string")
|
|
93
|
-
throw new Error("Unexpected JSON
|
|
109
|
+
throw new Error("Unexpected JSON scalar fragment");
|
|
94
110
|
length += token.value.length;
|
|
95
111
|
if (length > constants.MAX_STRING_LENGTH)
|
|
96
112
|
throw new RangeError("Invalid string length");
|
|
97
113
|
parts.push(token.value);
|
|
98
114
|
partLength += token.value.length;
|
|
99
|
-
if (partLength >=
|
|
115
|
+
if (partLength >= PACKED_TOKEN_PART_CODE_UNITS) {
|
|
100
116
|
// The tokenizer emits short fragments. Coalesce them before retaining
|
|
101
|
-
// a
|
|
117
|
+
// a scalar so millions of substring/rope nodes cannot exhaust the heap
|
|
102
118
|
// before the native string-length constraint can be reported.
|
|
103
|
-
requireStringAssemblyHeadroom(operation, inputFileBytes, length);
|
|
119
|
+
requireStringAssemblyHeadroom(operation, inputFileBytes, path, length);
|
|
104
120
|
value += parts.join("");
|
|
105
121
|
parts = [];
|
|
106
122
|
partLength = 0;
|
|
@@ -108,9 +124,10 @@ const packJsonStrings = (operation, inputFileBytes) => async function* (tokens)
|
|
|
108
124
|
break;
|
|
109
125
|
case "endKey":
|
|
110
126
|
case "endString":
|
|
127
|
+
case "endNumber":
|
|
111
128
|
if (kind === undefined)
|
|
112
|
-
throw new Error("Unexpected JSON
|
|
113
|
-
requireStringAssemblyHeadroom(operation, inputFileBytes, length);
|
|
129
|
+
throw new Error("Unexpected JSON scalar end");
|
|
130
|
+
requireStringAssemblyHeadroom(operation, inputFileBytes, path, length);
|
|
114
131
|
yield { name: kind, value: value + parts.join("") };
|
|
115
132
|
kind = undefined;
|
|
116
133
|
length = 0;
|
|
@@ -123,15 +140,58 @@ const packJsonStrings = (operation, inputFileBytes) => async function* (tokens)
|
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
};
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
/** Admit the retained value graph before the upstream assembler grows it. */
|
|
144
|
+
const admitJsonAssembly = (operation, inputFileBytes, path) => async function* (tokens) {
|
|
145
|
+
let projectedBytes = 0;
|
|
146
|
+
let nextCheck = 0;
|
|
147
|
+
for await (const token of tokens) {
|
|
148
|
+
if (typeof token !== "object" || token === null || !("name" in token))
|
|
149
|
+
throw new Error("Unexpected JSON assembly token");
|
|
150
|
+
if (token.name === "startObject" || token.name === "startArray") {
|
|
151
|
+
projectedBytes += 128;
|
|
152
|
+
}
|
|
153
|
+
else if (token.name === "keyValue" || token.name === "stringValue") {
|
|
154
|
+
if (!("value" in token) || typeof token.value !== "string")
|
|
155
|
+
throw new Error("Unexpected packed JSON string");
|
|
156
|
+
projectedBytes += 64 + token.value.length * 2;
|
|
157
|
+
}
|
|
158
|
+
else if (token.name === "numberValue" ||
|
|
159
|
+
token.name === "nullValue" ||
|
|
160
|
+
token.name === "trueValue" ||
|
|
161
|
+
token.name === "falseValue") {
|
|
162
|
+
projectedBytes += 64;
|
|
163
|
+
}
|
|
164
|
+
if (projectedBytes >= nextCheck) {
|
|
165
|
+
const heap = getHeapStatistics();
|
|
166
|
+
// Conservative capacity for containers, property/array slots and UTF-16
|
|
167
|
+
// values. Keep another whole projection available for container growth,
|
|
168
|
+
// plus the next chunk of estimates between samples. This is admission
|
|
169
|
+
// against live runtime headroom, not a fixed document-size policy.
|
|
170
|
+
const requiredBytes = projectedBytes + READ_CHUNK_BYTES;
|
|
171
|
+
if (requiredBytes > heap.total_available_size)
|
|
172
|
+
throw new AnalysisResourceConstraintError(operation, "memory", "Insufficient heap headroom to materialize the complete JSON value", {
|
|
173
|
+
input_path: path,
|
|
174
|
+
input_file_bytes: inputFileBytes,
|
|
175
|
+
projected_value_bytes: projectedBytes,
|
|
176
|
+
assembly_headroom_bytes: requiredBytes,
|
|
177
|
+
available_heap_bytes: heap.total_available_size,
|
|
178
|
+
heap_size_limit_bytes: heap.heap_size_limit,
|
|
179
|
+
}, { remediationAction: JSON_INPUT_RESOURCE_REMEDIATION });
|
|
180
|
+
nextCheck = projectedBytes + READ_CHUNK_BYTES;
|
|
181
|
+
}
|
|
182
|
+
yield token;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const requireStringAssemblyHeadroom = (operation, inputFileBytes, path, stringCodeUnits) => {
|
|
186
|
+
if (stringCodeUnits < PACKED_TOKEN_PART_CODE_UNITS)
|
|
128
187
|
return;
|
|
129
188
|
const heap = getHeapStatistics();
|
|
130
189
|
// Concatenation or key interning may flatten the retained rope. Reserve its
|
|
131
190
|
// UTF-16 representation and the next coalesced part before that allocation.
|
|
132
|
-
const requiredBytes = 2 * (stringCodeUnits +
|
|
191
|
+
const requiredBytes = 2 * (stringCodeUnits + PACKED_TOKEN_PART_CODE_UNITS);
|
|
133
192
|
if (requiredBytes > heap.total_available_size)
|
|
134
193
|
throw new AnalysisResourceConstraintError(operation, "memory", "Insufficient heap headroom to assemble a complete JSON string", {
|
|
194
|
+
input_path: path,
|
|
135
195
|
input_file_bytes: inputFileBytes,
|
|
136
196
|
string_code_units: stringCodeUnits,
|
|
137
197
|
string_assembly_headroom_bytes: requiredBytes,
|
|
@@ -141,25 +201,39 @@ const requireStringAssemblyHeadroom = (operation, inputFileBytes, stringCodeUnit
|
|
|
141
201
|
remediationAction: JSON_INPUT_RESOURCE_REMEDIATION,
|
|
142
202
|
});
|
|
143
203
|
};
|
|
144
|
-
async function* decodedChunks(handle,
|
|
204
|
+
async function* decodedChunks(handle, admittedBytes, path, signal) {
|
|
145
205
|
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
206
|
+
let leading = true;
|
|
207
|
+
const checked = (text) => {
|
|
208
|
+
if (leading && text.length > 0) {
|
|
209
|
+
leading = false;
|
|
210
|
+
if (text.startsWith("\uFEFF"))
|
|
211
|
+
throw new JsonByteOrderMarkError();
|
|
152
212
|
}
|
|
213
|
+
return text;
|
|
214
|
+
};
|
|
153
215
|
const bytes = Buffer.allocUnsafe(READ_CHUNK_BYTES);
|
|
216
|
+
let observedBytes = 0;
|
|
154
217
|
while (true) {
|
|
155
218
|
signal?.throwIfAborted();
|
|
156
|
-
const read = await handle.read(bytes, 0, bytes.length, null);
|
|
219
|
+
const read = await handle.read(bytes, 0, Math.min(bytes.length, admittedBytes - observedBytes + 1), null);
|
|
157
220
|
signal?.throwIfAborted();
|
|
158
221
|
if (read.bytesRead === 0)
|
|
159
222
|
break;
|
|
160
|
-
|
|
223
|
+
observedBytes += read.bytesRead;
|
|
224
|
+
if (observedBytes > admittedBytes)
|
|
225
|
+
throw new RegularFileChangedError(path);
|
|
226
|
+
yield checked(decoder.decode(bytes.subarray(0, read.bytesRead), { stream: true }));
|
|
227
|
+
}
|
|
228
|
+
if (observedBytes !== admittedBytes)
|
|
229
|
+
throw new RegularFileChangedError(path);
|
|
230
|
+
yield checked(decoder.decode());
|
|
231
|
+
}
|
|
232
|
+
/** A streamed JSON file begins with a byte-order mark; reported as invalid JSON. */
|
|
233
|
+
class JsonByteOrderMarkError extends SyntaxError {
|
|
234
|
+
constructor() {
|
|
235
|
+
super(JSON_BYTE_ORDER_MARK_MESSAGE);
|
|
161
236
|
}
|
|
162
|
-
yield decoder.decode();
|
|
163
237
|
}
|
|
164
238
|
const readPrefix = async (handle, size, signal) => {
|
|
165
239
|
const bytes = Buffer.allocUnsafe(size);
|
|
@@ -172,8 +246,7 @@ const readPrefix = async (handle, size, signal) => {
|
|
|
172
246
|
return { bytes: bytes.subarray(0, offset), complete: true };
|
|
173
247
|
offset += read.bytesRead;
|
|
174
248
|
}
|
|
175
|
-
//
|
|
176
|
-
// the prefix already read rather than reopening or dropping its bytes.
|
|
249
|
+
// One byte beyond the admitted extent proves the selected file changed.
|
|
177
250
|
return { bytes, complete: false };
|
|
178
251
|
};
|
|
179
252
|
const invalidJson = (operation, message, cause) => new AnalysisInputError(operation, cause === undefined ? undefined : { cause }, [{ path: [], reason: "invalid_format", expected: "JSON", message }]);
|