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
|
@@ -7,25 +7,33 @@ import { ArtifactReaderFailure, } from "../ArtifactReader.js";
|
|
|
7
7
|
import { abortIfNeeded } from "../ArtifactHash.js";
|
|
8
8
|
import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
|
|
9
9
|
import { SafeOutputTree } from "../SafeOutputTree.js";
|
|
10
|
+
import { SafeOutputTreeCreationFailure } from "../SafeOutputTreeCreationFailure.js";
|
|
10
11
|
import { ZipArtifactReader } from "../ZipArtifactReader.js";
|
|
11
12
|
import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js";
|
|
12
13
|
import { artifactExtractionResultSchema, } from "../../domain/artifactGraph.js";
|
|
13
14
|
import { AnalysisUnsupportedTargetError } from "../../domain/analysisErrorCore.js";
|
|
14
|
-
import {
|
|
15
|
+
import {} from "../ArtifactResourceScope.js";
|
|
16
|
+
import { scanArtifactInventoryInScope } from "../inventory/ArtifactInventory.js";
|
|
15
17
|
/** Extract every regular inventory occurrence into an exclusively owned absent root. */
|
|
16
|
-
export const extractArtifact = async (input, signal) =>
|
|
18
|
+
export const extractArtifact = async (input, signal) => input.resourceScope.run(() => extractArtifactInScope(input, signal));
|
|
19
|
+
const extractArtifactInScope = async (input, signal) => {
|
|
17
20
|
// Cancellation wins over every later refusal, including unsupported formats.
|
|
18
21
|
abortIfNeeded(signal);
|
|
19
22
|
const sourcePath = await realpath(input.inputPath);
|
|
20
23
|
await requireExtractableFormat(sourcePath, input);
|
|
21
|
-
const snapshot = await
|
|
24
|
+
const snapshot = await scanArtifactInventoryInScope(sourcePath, {
|
|
25
|
+
resourceScope: input.resourceScope,
|
|
22
26
|
signal,
|
|
23
27
|
environment: input.environment,
|
|
28
|
+
integrity: { mode: input.integrityPolicy },
|
|
24
29
|
});
|
|
25
|
-
return
|
|
30
|
+
return materializeArtifactInventoryInScope(input, sourcePath, snapshot, signal);
|
|
26
31
|
};
|
|
27
32
|
/** Materialize a scanned inventory, verifying every current occurrence against it. */
|
|
28
33
|
export const materializeArtifactInventory = async (input, sourcePath, snapshot, signal) => {
|
|
34
|
+
return input.resourceScope.run(() => materializeArtifactInventoryInScope(input, sourcePath, snapshot, signal));
|
|
35
|
+
};
|
|
36
|
+
const materializeArtifactInventoryInScope = async (input, sourcePath, snapshot, signal) => {
|
|
29
37
|
abortIfNeeded(signal);
|
|
30
38
|
const selectedOccurrences = snapshot.occurrences.filter((occurrence) => (occurrence.entry_kind === "file" || occurrence.entry_kind === "slice") &&
|
|
31
39
|
occurrence.logical_path !== ".");
|
|
@@ -42,26 +50,36 @@ export const materializeArtifactInventory = async (input, sourcePath, snapshot,
|
|
|
42
50
|
return true;
|
|
43
51
|
});
|
|
44
52
|
const selectedIds = new Set(activeOccurrences.map(({ occurrence_id: id }) => id));
|
|
45
|
-
const
|
|
46
|
-
const neededNodes = new Set();
|
|
47
|
-
collectOccurrences(snapshot.occurrences, selectedIds, occurrences, neededNodes);
|
|
53
|
+
const neededNodes = new Set(activeOccurrences.map(({ artifact_id: id }) => id));
|
|
48
54
|
const nodes = new Map();
|
|
49
|
-
|
|
55
|
+
for (const node of snapshot.nodes)
|
|
56
|
+
if (neededNodes.has(node.artifact_id))
|
|
57
|
+
nodes.set(node.artifact_id, node);
|
|
50
58
|
const inventory = {
|
|
51
59
|
manifest: snapshot.manifest,
|
|
52
|
-
|
|
53
|
-
nodes,
|
|
60
|
+
integrityContradictions: snapshot.integrity_contradictions.filter(({ occurrence_id: id }) => selectedIds.has(id)),
|
|
54
61
|
};
|
|
55
62
|
const selected = activeOccurrences.map((occurrence) => {
|
|
56
63
|
// REA never decrypts archive entries, so an encrypted entry makes the
|
|
57
64
|
// complete extraction unsupported rather than the archive invalid.
|
|
58
65
|
if (occurrence.encrypted)
|
|
59
66
|
throw new AnalysisUnsupportedTargetError("extract_artifact", input.inputPath, `Archive entry ${occurrence.logical_path} is encrypted; REA does not decrypt archive entries, so the archive cannot be extracted completely`);
|
|
67
|
+
// Inventory keeps an ASAR unpacked entry whose companion file is absent,
|
|
68
|
+
// but extraction cannot materialize bytes it never observed.
|
|
69
|
+
if (occurrence.entry_kind === "file" &&
|
|
70
|
+
occurrence.artifact_id === null &&
|
|
71
|
+
occurrence.hash_status === "unavailable")
|
|
72
|
+
throw new ArtifactReaderFailure("unavailable", `ASAR unpacked companion bytes are unavailable for ${occurrence.logical_path}`, undefined, {
|
|
73
|
+
logicalPath: occurrence.logical_path,
|
|
74
|
+
declaredSha256: null,
|
|
75
|
+
calculatedSha256: null,
|
|
76
|
+
unpacked: true,
|
|
77
|
+
});
|
|
60
78
|
if ((occurrence.entry_kind !== "file" && occurrence.entry_kind !== "slice") ||
|
|
61
79
|
occurrence.artifact_id === null ||
|
|
62
80
|
occurrence.logical_path === ".")
|
|
63
81
|
throw new ArtifactReaderFailure("format", `Selected occurrence is not an extractable regular child file: ${occurrence.logical_path} (${occurrence.occurrence_id})`);
|
|
64
|
-
const node =
|
|
82
|
+
const node = nodes.get(occurrence.artifact_id);
|
|
65
83
|
if (node === undefined)
|
|
66
84
|
throw new ArtifactReaderFailure("integrity", `Selected occurrence has no inventory node: ${occurrence.occurrence_id}`);
|
|
67
85
|
return { occurrence, node };
|
|
@@ -77,74 +95,36 @@ export const materializeArtifactInventory = async (input, sourcePath, snapshot,
|
|
|
77
95
|
const materializeSelection = async ({ input, sourcePath, inventory, selected, signal, }) => {
|
|
78
96
|
const byPath = new Map(selected.map((item) => [item.occurrence.logical_path, item]));
|
|
79
97
|
const reader = await createReader(sourcePath, input);
|
|
98
|
+
const readerOwner = {
|
|
99
|
+
kind: "reader",
|
|
100
|
+
reader,
|
|
101
|
+
resource: `artifact reader for ${sourcePath}`,
|
|
102
|
+
};
|
|
103
|
+
let localReaderOwner = readerOwner;
|
|
80
104
|
let output;
|
|
81
|
-
let
|
|
82
|
-
let readerClosed = false;
|
|
105
|
+
let completed;
|
|
83
106
|
const extracted = [];
|
|
84
107
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (entry.kind === "file" || entry.kind === "slice")
|
|
93
|
-
throw new ArtifactReaderFailure("integrity", `Regular artifact entry is missing from inventory: ${path}`);
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
preflight(entry);
|
|
97
|
-
const stream = await reader.open(entry, signal);
|
|
98
|
-
const written = await output.write(path, stream, selectedItem.node.sha256, signal);
|
|
99
|
-
extracted.push({
|
|
100
|
-
artifact_id: selectedItem.node.artifact_id,
|
|
101
|
-
relative_path: written.relativePath,
|
|
102
|
-
sha256: written.sha256,
|
|
103
|
-
bytes_written: written.bytesWritten,
|
|
104
|
-
created: true,
|
|
105
|
-
});
|
|
106
|
-
byPath.delete(path);
|
|
108
|
+
try {
|
|
109
|
+
output = await SafeOutputTree.create(input.outputRoot);
|
|
110
|
+
}
|
|
111
|
+
catch (cause) {
|
|
112
|
+
if (cause instanceof SafeOutputTreeCreationFailure)
|
|
113
|
+
output = cause.tree;
|
|
114
|
+
throw cause;
|
|
107
115
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
await writeSelectedEntries({ reader, output, byPath, extracted, signal });
|
|
117
|
+
localReaderOwner = undefined;
|
|
118
|
+
const closeAttempt = await input.resourceScope.release(readerOwner);
|
|
119
|
+
if (closeAttempt.kind === "failed")
|
|
120
|
+
throw ArtifactReaderFailure.withCleanup(closeAttempt.cause, ArtifactReaderFailure.cleanupObservation(closeAttempt.cause, readerOwner.resource));
|
|
113
121
|
extracted.sort((left, right) => compareUnicodeCodePoints(left.relative_path, right.relative_path));
|
|
114
|
-
|
|
122
|
+
completed = createExtractionResult(input, inventory, selected, extracted);
|
|
115
123
|
await output.commit();
|
|
116
|
-
return
|
|
124
|
+
return completed;
|
|
117
125
|
}
|
|
118
126
|
catch (cause) {
|
|
119
|
-
const cleanupFailures =
|
|
120
|
-
if (readerCloseAttempted && !readerClosed)
|
|
121
|
-
cleanupFailures.push({
|
|
122
|
-
cause,
|
|
123
|
-
resource: `artifact reader for ${sourcePath}`,
|
|
124
|
-
});
|
|
125
|
-
if (!readerCloseAttempted) {
|
|
126
|
-
try {
|
|
127
|
-
readerCloseAttempted = true;
|
|
128
|
-
await reader.close();
|
|
129
|
-
}
|
|
130
|
-
catch (cleanupCause) {
|
|
131
|
-
cleanupFailures.push({
|
|
132
|
-
cause: cleanupCause,
|
|
133
|
-
resource: `artifact reader for ${sourcePath}`,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (output !== undefined) {
|
|
138
|
-
try {
|
|
139
|
-
await output.rollback();
|
|
140
|
-
}
|
|
141
|
-
catch (cleanupCause) {
|
|
142
|
-
cleanupFailures.push({
|
|
143
|
-
cause: cleanupCause,
|
|
144
|
-
resource: input.outputRoot,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
127
|
+
const cleanupFailures = await releaseExtractionOwners(input.resourceScope, localReaderOwner, output, input.outputRoot);
|
|
148
128
|
if (cleanupFailures.length > 0) {
|
|
149
129
|
const observations = cleanupFailures.map(({ cause: cleanupCause, resource }) => ArtifactReaderFailure.cleanupObservation(cleanupCause, resource));
|
|
150
130
|
throw ArtifactReaderFailure.withCleanup(cause, {
|
|
@@ -152,11 +132,63 @@ const materializeSelection = async ({ input, sourcePath, inventory, selected, si
|
|
|
152
132
|
resources: [
|
|
153
133
|
...new Set(observations.flatMap(({ resources }) => resources)),
|
|
154
134
|
],
|
|
155
|
-
}
|
|
135
|
+
}, output?.published === true && completed !== undefined
|
|
136
|
+
? { kind: "artifact-extraction", extraction: completed }
|
|
137
|
+
: undefined);
|
|
156
138
|
}
|
|
139
|
+
if (output?.published === true && completed !== undefined)
|
|
140
|
+
return completed;
|
|
157
141
|
throw cause;
|
|
158
142
|
}
|
|
159
143
|
};
|
|
144
|
+
const writeSelectedEntries = async ({ reader, output, byPath, extracted, signal, }) => {
|
|
145
|
+
const registry = new ArtifactPathRegistry();
|
|
146
|
+
for await (const entry of reader.entries(signal)) {
|
|
147
|
+
const path = normalizeArtifactPath(entry.path);
|
|
148
|
+
registry.add(path, entry.kind);
|
|
149
|
+
const selectedItem = byPath.get(path);
|
|
150
|
+
if (selectedItem === undefined) {
|
|
151
|
+
if (entry.kind === "file" || entry.kind === "slice")
|
|
152
|
+
throw new ArtifactReaderFailure("integrity", `Regular artifact entry is missing from inventory: ${path}`);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
preflight(entry);
|
|
156
|
+
const stream = await reader.open(entry, signal);
|
|
157
|
+
const written = await output.write(path, stream, {
|
|
158
|
+
sha256: selectedItem.node.sha256,
|
|
159
|
+
bytes: selectedItem.node.size,
|
|
160
|
+
}, signal);
|
|
161
|
+
extracted.push({
|
|
162
|
+
artifact_id: selectedItem.node.artifact_id,
|
|
163
|
+
relative_path: written.relativePath,
|
|
164
|
+
sha256: written.sha256,
|
|
165
|
+
bytes_written: written.bytesWritten,
|
|
166
|
+
created: true,
|
|
167
|
+
});
|
|
168
|
+
byPath.delete(path);
|
|
169
|
+
}
|
|
170
|
+
if (byPath.size > 0)
|
|
171
|
+
throw new ArtifactReaderFailure("integrity", `Inventoried regular artifact entries were not materialized: ${[...byPath.keys()].sort(compareUnicodeCodePoints).join(", ")}`);
|
|
172
|
+
};
|
|
173
|
+
const releaseExtractionOwners = async (resourceScope, readerOwner, output, outputRoot) => {
|
|
174
|
+
const failures = [];
|
|
175
|
+
if (readerOwner !== undefined) {
|
|
176
|
+
const attempt = await resourceScope.release(readerOwner);
|
|
177
|
+
if (attempt.kind === "failed")
|
|
178
|
+
failures.push({ cause: attempt.cause, resource: readerOwner.resource });
|
|
179
|
+
}
|
|
180
|
+
if (output !== undefined) {
|
|
181
|
+
const owner = {
|
|
182
|
+
kind: "output-tree",
|
|
183
|
+
tree: output,
|
|
184
|
+
resource: outputRoot,
|
|
185
|
+
};
|
|
186
|
+
const attempt = await resourceScope.release(owner);
|
|
187
|
+
if (attempt.kind === "failed")
|
|
188
|
+
failures.push({ cause: attempt.cause, resource: owner.resource });
|
|
189
|
+
}
|
|
190
|
+
return failures;
|
|
191
|
+
};
|
|
160
192
|
const createExtractionResult = (input, inventory, selected, extracted) => {
|
|
161
193
|
const extractionSemantic = {
|
|
162
194
|
source_manifest_id: inventory.manifest.manifest_id,
|
|
@@ -177,25 +209,17 @@ const createExtractionResult = (input, inventory, selected, extracted) => {
|
|
|
177
209
|
containment_verified: true,
|
|
178
210
|
cleanup: { attempted: false, verified: true, residual_paths: [] },
|
|
179
211
|
provenance: [],
|
|
212
|
+
integrity_contradictions: inventory.integrityContradictions,
|
|
180
213
|
limitations: [
|
|
181
214
|
"All regular files in the active artifact were materialized; nested archive contents remain represented by their containing file.",
|
|
215
|
+
...(inventory.integrityContradictions.length === 0
|
|
216
|
+
? []
|
|
217
|
+
: [
|
|
218
|
+
`${String(inventory.integrityContradictions.length)} extracted file(s) contradict declared integrity metadata; their bytes are observed-untrusted.`,
|
|
219
|
+
]),
|
|
182
220
|
],
|
|
183
221
|
});
|
|
184
222
|
};
|
|
185
|
-
const collectOccurrences = (items, selected, output, neededNodes) => {
|
|
186
|
-
for (const item of items) {
|
|
187
|
-
if (!selected.has(item.occurrence_id))
|
|
188
|
-
continue;
|
|
189
|
-
output.set(item.occurrence_id, item);
|
|
190
|
-
if (item.artifact_id !== null)
|
|
191
|
-
neededNodes.add(item.artifact_id);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
const collectNodes = (items, selected, output) => {
|
|
195
|
-
for (const item of items)
|
|
196
|
-
if (selected.has(item.artifact_id))
|
|
197
|
-
output.set(item.artifact_id, item);
|
|
198
|
-
};
|
|
199
223
|
const ZIP_FORMATS = ["ipa", "apk", "msix", "appx", "zip"];
|
|
200
224
|
const isZipFormat = (format) => ZIP_FORMATS.includes(format);
|
|
201
225
|
/**
|
|
@@ -11,30 +11,54 @@ export const indexOccurrencesByPath = (occurrences) => {
|
|
|
11
11
|
byPath.set(occurrence.logical_path, occurrence);
|
|
12
12
|
return byPath;
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
?
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
:
|
|
36
|
-
|
|
37
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Create an occurrence before its bytes are read. A container suffix is not a
|
|
16
|
+
* container family until the bytes are classified, so a member named like a
|
|
17
|
+
* container starts with an unknown format.
|
|
18
|
+
*/
|
|
19
|
+
export const createOccurrence = (entry, path, parent) => {
|
|
20
|
+
const role = entry.kind === "directory"
|
|
21
|
+
? {
|
|
22
|
+
kind: path.toLowerCase().endsWith(".framework")
|
|
23
|
+
? "framework"
|
|
24
|
+
: "container",
|
|
25
|
+
format: "directory",
|
|
26
|
+
}
|
|
27
|
+
: containerSuffixFamily(path) === undefined
|
|
28
|
+
? classifyArtifactPath(path)
|
|
29
|
+
: { kind: "unknown", format: "unknown" };
|
|
30
|
+
return {
|
|
31
|
+
occurrence_id: `occ_${digestCanonicalValue({ path, kind: entry.kind }, "Artifact")}`,
|
|
32
|
+
artifact_id: null,
|
|
33
|
+
parent_occurrence_id: parent,
|
|
34
|
+
logical_path: path,
|
|
35
|
+
entry_kind: entry.kind,
|
|
36
|
+
artifact_kind: role.kind,
|
|
37
|
+
artifact_format: role.format,
|
|
38
|
+
declared_size: entry.declaredSize,
|
|
39
|
+
compressed_size: entry.compressedSize,
|
|
40
|
+
executable: entry.executable,
|
|
41
|
+
encrypted: entry.encrypted,
|
|
42
|
+
hash_status: entry.encrypted ? "unavailable" : "not-hashed",
|
|
43
|
+
source_location: entry.byteOffset === null || entry.declaredSize === null
|
|
44
|
+
? null
|
|
45
|
+
: { offset: entry.byteOffset, length: entry.declaredSize },
|
|
46
|
+
limitations: [...entry.limitations],
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/** Record that an unread member's container suffix was not checked against bytes. */
|
|
50
|
+
export const noteUnreadContainerSuffix = (occurrence) => {
|
|
51
|
+
if (occurrence.entry_kind === "directory")
|
|
52
|
+
return;
|
|
53
|
+
const family = containerSuffixFamily(occurrence.logical_path);
|
|
54
|
+
if (family === undefined)
|
|
55
|
+
return;
|
|
56
|
+
occurrence.limitations.push(`The path suffix suggests ${family.toUpperCase()}, but these bytes were not read, so the container family is unknown.`);
|
|
57
|
+
};
|
|
58
|
+
const containerSuffixFamily = (path) => {
|
|
59
|
+
const lower = path.toLowerCase();
|
|
60
|
+
return lower.endsWith(".asar") ? "asar" : zipPackageFormatForPath(lower);
|
|
61
|
+
};
|
|
38
62
|
/** Compare exact child names independently of host locale and traversal order. */
|
|
39
63
|
export const materializeDirectoryNodes = (occurrences, nodes) => {
|
|
40
64
|
const directories = occurrences
|
|
@@ -153,15 +177,13 @@ export const createArtifactEdges = (rootArtifactId, occurrences, producer) => {
|
|
|
153
177
|
rootArtifactId;
|
|
154
178
|
const semantic = {
|
|
155
179
|
parent_artifact_id: parentArtifactId,
|
|
156
|
-
child_artifact_id: occurrence.artifact_id,
|
|
157
180
|
relation: occurrence.entry_kind === "slice"
|
|
158
181
|
? "slice-of"
|
|
159
182
|
: relationFor(occurrence.logical_path),
|
|
160
183
|
occurrence_id: occurrence.occurrence_id,
|
|
161
|
-
logical_path: occurrence.logical_path,
|
|
162
184
|
};
|
|
163
185
|
edges.push({
|
|
164
|
-
edge_id: artifactEdgeId(semantic),
|
|
186
|
+
edge_id: artifactEdgeId(semantic, occurrence),
|
|
165
187
|
...semantic,
|
|
166
188
|
producer: occurrence.entry_kind === "slice" ? (producer ?? null) : null,
|
|
167
189
|
ordinal: edges.length,
|
|
@@ -169,29 +191,55 @@ export const createArtifactEdges = (rootArtifactId, occurrences, producer) => {
|
|
|
169
191
|
}
|
|
170
192
|
return edges;
|
|
171
193
|
};
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
194
|
+
/** Resolve strict observed ancestors without rebuilding every path prefix. */
|
|
195
|
+
export const resolveOccurrenceParents = (occurrences, byPath, expandedContainerIds) => {
|
|
196
|
+
const root = { children: new Map() };
|
|
197
|
+
for (const occurrence of byPath.values()) {
|
|
198
|
+
if (occurrence.entry_kind !== "directory" &&
|
|
199
|
+
!expandedContainerIds.has(occurrence.occurrence_id))
|
|
200
|
+
continue;
|
|
201
|
+
let branch = root;
|
|
202
|
+
for (const segment of occurrence.logical_path.split("/")) {
|
|
203
|
+
let child = branch.children.get(segment);
|
|
204
|
+
if (child === undefined) {
|
|
205
|
+
child = { children: new Map() };
|
|
206
|
+
branch.children.set(segment, child);
|
|
207
|
+
}
|
|
208
|
+
branch = child;
|
|
209
|
+
}
|
|
210
|
+
branch.occurrence = occurrence;
|
|
211
|
+
}
|
|
212
|
+
for (const occurrence of occurrences) {
|
|
213
|
+
const path = occurrence.logical_path;
|
|
214
|
+
let branch = root;
|
|
215
|
+
let parent;
|
|
216
|
+
// Walk parent segments only. Stop scanning the path once no observed
|
|
217
|
+
// directory or expanded container can be an ancestor.
|
|
218
|
+
for (let start = 0;;) {
|
|
219
|
+
const slash = path.indexOf("/", start);
|
|
220
|
+
if (slash < 0)
|
|
221
|
+
break;
|
|
222
|
+
const segment = path.slice(start, slash);
|
|
223
|
+
const child = branch.children.get(segment);
|
|
224
|
+
if (child === undefined)
|
|
225
|
+
break;
|
|
226
|
+
branch = child;
|
|
227
|
+
parent = branch.occurrence ?? parent;
|
|
228
|
+
start = slash + 1;
|
|
229
|
+
}
|
|
230
|
+
occurrence.parent_occurrence_id = parent?.occurrence_id ?? null;
|
|
181
231
|
}
|
|
182
|
-
return undefined;
|
|
183
232
|
};
|
|
233
|
+
/**
|
|
234
|
+
* Assign a path role hint. Container families are not path roles: ZIP and
|
|
235
|
+
* ASAR families are chosen only after their bytes have been classified.
|
|
236
|
+
*/
|
|
184
237
|
export const classifyArtifactPath = (path) => {
|
|
185
238
|
const lower = path.toLowerCase();
|
|
186
239
|
if (lower.endsWith(".map"))
|
|
187
240
|
return { kind: "source-map", format: "source-map" };
|
|
188
241
|
if (/\.(?:m?js|cjs)$/u.test(lower))
|
|
189
242
|
return { kind: "javascript", format: "javascript-bundle" };
|
|
190
|
-
if (lower.endsWith(".asar"))
|
|
191
|
-
return { kind: "container", format: "asar" };
|
|
192
|
-
const archiveFormat = zipPackageFormatForPath(lower);
|
|
193
|
-
if (archiveFormat !== undefined)
|
|
194
|
-
return { kind: "container", format: archiveFormat };
|
|
195
243
|
if (/\.framework(?:\/|$)/u.test(lower))
|
|
196
244
|
return { kind: "framework", format: "file" };
|
|
197
245
|
if (/\.(?:node|dylib|so)$/u.test(lower))
|
|
@@ -207,7 +255,26 @@ export const classifyArtifactPath = (path) => {
|
|
|
207
255
|
};
|
|
208
256
|
/** Classify executable formats from bytes while retaining path-specific roles. */
|
|
209
257
|
export const classifyArtifactContent = (path, prefix, fileSize = prefix.length) => {
|
|
210
|
-
|
|
258
|
+
const format = classifyArtifactBytes(prefix, fileSize);
|
|
259
|
+
if (format === "file" &&
|
|
260
|
+
path.toLowerCase().endsWith(".asar") &&
|
|
261
|
+
hasAsarHeader(prefix))
|
|
262
|
+
return { kind: "container", format: "asar" };
|
|
263
|
+
return artifactRoleForFormat(path, format);
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* Electron ASAR starts with a size pickle whose payload is one uint32, then
|
|
267
|
+
* a header pickle whose payload begins with a JSON object.
|
|
268
|
+
*/
|
|
269
|
+
export const hasAsarHeader = (prefix) => {
|
|
270
|
+
if (prefix.length < 17 || prefix.readUInt32LE(0) !== 4)
|
|
271
|
+
return false;
|
|
272
|
+
const headerSize = prefix.readUInt32LE(4);
|
|
273
|
+
const payloadSize = prefix.readUInt32LE(8);
|
|
274
|
+
if (headerSize < 16 || payloadSize !== headerSize - 4)
|
|
275
|
+
return false;
|
|
276
|
+
const stringLength = prefix.readUInt32LE(12);
|
|
277
|
+
return (stringLength >= 2 && stringLength <= payloadSize - 4 && prefix[16] === 0x7b);
|
|
211
278
|
};
|
|
212
279
|
const artifactRoleForFormat = (path, format) => {
|
|
213
280
|
const byPath = classifyArtifactPath(path);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { realpath } from "node:fs/promises";
|
|
2
2
|
import { artifactInventoryResultSchema, } from "../../domain/artifactGraph.js";
|
|
3
3
|
import { abortIfNeeded } from "../ArtifactHash.js";
|
|
4
|
-
import {
|
|
4
|
+
import { scanCanonicalArtifactInventoryInScope } from "./scanCanonical.js";
|
|
5
5
|
/** Inventory one local artifact and return every graph collection inline. */
|
|
6
|
-
export const inventoryArtifact = async (inputPath, options
|
|
6
|
+
export const inventoryArtifact = async (inputPath, options) => {
|
|
7
7
|
const snapshot = await scanArtifactInventory(inputPath, options);
|
|
8
8
|
return artifactInventoryResultSchema.parse(snapshot);
|
|
9
9
|
};
|
|
10
10
|
/** Scan an artifact once and retain the complete immutable graph for projection. */
|
|
11
|
-
export const scanArtifactInventory = async (inputPath, options
|
|
11
|
+
export const scanArtifactInventory = async (inputPath, options) => options.resourceScope.run(() => scanArtifactInventoryInScope(inputPath, options));
|
|
12
|
+
export const scanArtifactInventoryInScope = async (inputPath, options) => {
|
|
12
13
|
abortIfNeeded(options.signal);
|
|
13
14
|
const path = await realpath(inputPath);
|
|
14
|
-
return
|
|
15
|
+
return scanCanonicalArtifactInventoryInScope(path, options);
|
|
15
16
|
};
|
|
@@ -1,53 +1,96 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sameRegularFileState } from "../../filesystem/RegularFile.js";
|
|
2
2
|
import { classifyArtifactContent } from "./ArtifactGraphConstruction.js";
|
|
3
3
|
import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "../ArtifactHash.js";
|
|
4
4
|
import { hasZipSignature, zipPackageFormatForPath, } from "../../domain/zipPackageFormat.js";
|
|
5
5
|
import { ArtifactReaderFailure } from "../ArtifactReader.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const lower = path.toLowerCase();
|
|
9
|
-
const zipPackage = zipPackageFormatForPath(lower);
|
|
10
|
-
if (zipPackage !== undefined)
|
|
11
|
-
return zipPackage;
|
|
12
|
-
for (const format of ["asar", "dmg", "pkg"])
|
|
13
|
-
if (lower.endsWith(`.${format}`))
|
|
14
|
-
return format;
|
|
15
|
-
return undefined;
|
|
16
|
-
};
|
|
6
|
+
import {} from "../ArtifactResourceScope.js";
|
|
7
|
+
import { hashStableRootArtifactHandle, openRootArtifact, } from "./hashStableRootArtifact.js";
|
|
17
8
|
/** Classify and hash one file root through the same stable open descriptor. */
|
|
18
|
-
export const classifyAndHashRoot = async (path, directory, expectedMetadata,
|
|
9
|
+
export const classifyAndHashRoot = async (path, directory, expectedMetadata, options) => {
|
|
10
|
+
return options.resourceScope.run(async () => {
|
|
11
|
+
const result = await classifyAndHashRootForInventory(path, directory, expectedMetadata, options);
|
|
12
|
+
const rootSource = result.rootSource;
|
|
13
|
+
if (rootSource !== undefined) {
|
|
14
|
+
const owner = {
|
|
15
|
+
kind: "file-handle",
|
|
16
|
+
handle: rootSource.owner,
|
|
17
|
+
resource: `root artifact descriptor for ${path}`,
|
|
18
|
+
};
|
|
19
|
+
const cleanupAttempt = await options.resourceScope.release(owner);
|
|
20
|
+
if (cleanupAttempt.kind === "failed")
|
|
21
|
+
throw ArtifactReaderFailure.withCleanup(cleanupAttempt.cause, ArtifactReaderFailure.cleanupObservation(cleanupAttempt.cause, owner.resource));
|
|
22
|
+
}
|
|
23
|
+
return { format: result.format, digest: result.digest };
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
/** Classify a root and retain its admitted ZIP descriptor for child inventory. */
|
|
27
|
+
export const classifyAndHashRootForInventory = async (path, directory, expectedMetadata, options) => {
|
|
19
28
|
if (directory)
|
|
20
|
-
return { format: "directory", digest: null };
|
|
21
|
-
const
|
|
29
|
+
return { format: "directory", digest: null, rootSource: undefined };
|
|
30
|
+
const ownedHandle = await openRootArtifact(path, options.resourceScope, options.signal);
|
|
31
|
+
const handle = ownedHandle.handle;
|
|
32
|
+
const owner = {
|
|
33
|
+
kind: "file-handle",
|
|
34
|
+
handle: ownedHandle,
|
|
35
|
+
resource: `root artifact descriptor for ${path}`,
|
|
36
|
+
};
|
|
37
|
+
let outcome;
|
|
22
38
|
try {
|
|
23
39
|
const initial = await handle.stat();
|
|
24
40
|
if (!sameRegularFileState(expectedMetadata, initial))
|
|
25
41
|
throw new ArtifactReaderFailure("integrity", `Root artifact changed before inventory: ${path}`);
|
|
26
|
-
const format =
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
const format = await classifyRootFormat(path, handle);
|
|
43
|
+
const digest = await hashStableRootArtifactHandle(path, handle, initial, options.signal);
|
|
44
|
+
const retainSource = isZipFormat(format) || format === "mach-o-universal";
|
|
45
|
+
outcome = {
|
|
46
|
+
kind: "completed",
|
|
47
|
+
value: {
|
|
48
|
+
format,
|
|
49
|
+
digest,
|
|
50
|
+
rootSource: retainSource
|
|
51
|
+
? { handle, initial, owner: ownedHandle }
|
|
52
|
+
: undefined,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
38
55
|
}
|
|
39
56
|
catch (cause) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
outcome = { kind: "failed", cause };
|
|
58
|
+
}
|
|
59
|
+
if (outcome.kind === "failed" || outcome.value.rootSource === undefined) {
|
|
60
|
+
const cleanupAttempt = await options.resourceScope.release(owner);
|
|
61
|
+
if (cleanupAttempt.kind === "failed")
|
|
62
|
+
throw ArtifactReaderFailure.withCleanup(outcome.kind === "failed" ? outcome.cause : cleanupAttempt.cause, ArtifactReaderFailure.cleanupObservation(cleanupAttempt.cause, owner.resource));
|
|
43
63
|
}
|
|
64
|
+
if (outcome.kind === "failed")
|
|
65
|
+
throw outcome.cause;
|
|
66
|
+
return outcome.value;
|
|
44
67
|
};
|
|
45
|
-
const
|
|
68
|
+
const isZipFormat = (format) => format === "zip" ||
|
|
69
|
+
format === "ipa" ||
|
|
70
|
+
format === "apk" ||
|
|
71
|
+
format === "msix" ||
|
|
72
|
+
format === "appx";
|
|
73
|
+
const classifyRootFormat = async (path, handle) => {
|
|
46
74
|
const magic = Buffer.alloc(ARTIFACT_CLASSIFICATION_PREFIX_BYTES);
|
|
47
75
|
const observed = await handle.read(magic, 0, magic.length, 0);
|
|
48
76
|
const prefix = magic.subarray(0, observed.bytesRead);
|
|
77
|
+
const lower = path.toLowerCase();
|
|
49
78
|
if (hasZipSignature(prefix))
|
|
50
|
-
return "zip";
|
|
79
|
+
return zipPackageFormatForPath(lower) ?? "zip";
|
|
80
|
+
if (lower.endsWith(".pkg") &&
|
|
81
|
+
prefix.subarray(0, 4).toString("ascii") === "xar!")
|
|
82
|
+
return "pkg";
|
|
83
|
+
if (lower.endsWith(".dmg") && (await hasKolyTrailer(handle)))
|
|
84
|
+
return "dmg";
|
|
85
|
+
// ASAR is chosen from its header pickle; any other suffix is a role hint.
|
|
51
86
|
return classifyArtifactContent(path, prefix, (await handle.stat()).size)
|
|
52
87
|
.format;
|
|
53
88
|
};
|
|
89
|
+
const hasKolyTrailer = async (handle) => {
|
|
90
|
+
const size = (await handle.stat()).size;
|
|
91
|
+
if (size < 512)
|
|
92
|
+
return false;
|
|
93
|
+
const trailer = Buffer.alloc(4);
|
|
94
|
+
const read = await handle.read(trailer, 0, trailer.length, size - 512);
|
|
95
|
+
return read.bytesRead === 4 && trailer.toString("ascii") === "koly";
|
|
96
|
+
};
|