rea-agents 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -30
- package/bridge/ghidra/ReaGhidraBridge.java +358 -15
- package/bridge/ghidra/ReaGhidraExtensions.java +113 -0
- package/bridge/ghidra/ReaGhidraPrepareCom.java +32 -0
- package/dist/android/AndroidTargetSnapshot.js +34 -0
- package/dist/android/JadxAnalysis.js +191 -0
- package/dist/android/JadxConfiguration.js +41 -0
- package/dist/android/JadxMcpTransport.js +145 -0
- package/dist/android/JadxProtocol.js +101 -0
- package/dist/android/JadxProvider.js +170 -0
- package/dist/android/JadxRelease.js +19 -0
- package/dist/android/JadxSession.js +97 -0
- package/dist/application/AnalysisContextQueries.js +2 -1
- package/dist/application/AnalysisProviderEvaluation.js +5 -3
- package/dist/application/AnalysisProviderRegistry.js +2 -1
- package/dist/application/AnalysisSnapshotCache.js +4 -1
- package/dist/application/AnalysisSnapshotFiles.js +1 -1
- package/dist/application/AndroidAnalysisPort.js +1 -0
- package/dist/application/AndroidAnalysisService.js +37 -0
- package/dist/application/ArtifactExtraction.js +7 -4
- package/dist/application/ArtifactGraphConstruction.js +10 -17
- package/dist/application/ArtifactInventory/scanCanonical.js +8 -7
- package/dist/application/BinarySession.js +16 -3
- package/dist/application/BinarySessionExecution.js +4 -1
- package/dist/application/BinarySessionOpen.js +3 -2
- package/dist/application/BinarySessionRecords.js +9 -3
- package/dist/application/BinaryTargetResolver.js +25 -6
- package/dist/application/BrowserObservationService.js +2 -1
- package/dist/application/BrowserScenarioCaptureService.js +2 -1
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/CallPathTracing.js +2 -1
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/ClientConfigPath.js +3 -1
- package/dist/application/ClientConfigurationDocument.js +11 -1
- package/dist/application/ClientRegistrationStatus.js +8 -1
- package/dist/application/CompositeProvider.js +1 -1
- package/dist/application/DirectAnalysis.js +23 -7
- package/dist/application/DirectAnalysisStatus.js +3 -3
- package/dist/application/Doctor.js +48 -8
- package/dist/application/DoctorDiagnostics.js +7 -5
- package/dist/application/DoctorScope.js +1 -1
- package/dist/application/ElectronActiveEvidence.js +2 -2
- package/dist/application/ElectronActiveObservationService.js +2 -1
- package/dist/application/ElectronBoundaryAnalysis.js +1 -1
- package/dist/application/ElectronObservationService.js +2 -1
- package/dist/application/EnhancedLiteralTracing.js +2 -1
- package/dist/application/EnhancedToolTypes.js +2 -1
- package/dist/application/EnhancedTools.js +3 -1
- package/dist/application/EvidenceBundleCommands.js +2 -1
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/EvidenceInputResolver.js +30 -0
- package/dist/application/EvidenceLedger.js +2 -1
- package/dist/application/FirmwareAnalysisPort.js +1 -0
- package/dist/application/FirmwareAnalysisService.js +35 -0
- package/dist/application/FunctionAnalysisEvidence.js +32 -0
- package/dist/application/InventoryProjectionEvidence.js +2 -1
- package/dist/application/JavaScriptApplicationService.js +50 -3
- package/dist/application/JavaScriptApplicationWorkflowService.js +2 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +4 -2
- package/dist/application/JavaScriptArtifactFiles.js +4 -2
- package/dist/application/JavaScriptArtifactPathResolution.js +6 -2
- package/dist/application/JavaScriptJsonModules.js +3 -2
- package/dist/application/JavaScriptModuleRelationships.js +4 -2
- package/dist/application/JavaScriptRuntimeObservationService.js +2 -1
- package/dist/application/JavaScriptRuntimeReconciliationService.js +2 -1
- package/dist/application/JavaScriptSemanticGraphProjection.js +1 -1
- package/dist/application/JavaScriptSemanticTraceService.js +2 -1
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +3 -1
- package/dist/application/LinuxHopper.js +12 -4
- package/dist/application/MacHopper.js +20 -7
- package/dist/application/ManagedApplicationGraphService.js +2 -1
- package/dist/application/ManagedMemberComparisonService.js +3 -1
- package/dist/application/ManagedNativeVerificationService.js +2 -1
- package/dist/application/ManagedReconstructionService.js +2 -1
- package/dist/application/NativeCallRoutes.js +1 -1
- package/dist/application/NativeDispatchMetadataInspection.js +1 -1
- package/dist/application/NativeUiActionTrace.js +2 -1
- package/dist/application/NativeValueTrace.js +1 -1
- package/dist/application/ProcessCaptureError.js +1 -1
- package/dist/application/ProcessCaptureJournal.js +3 -1
- package/dist/application/ProcessCaptureLifecycle.js +6 -3
- package/dist/application/ProcessCli.js +9 -5
- package/dist/application/ProcessEvidence.js +2 -6
- package/dist/application/ProcessHarness.js +3 -2
- package/dist/application/ProcessNormalization.js +12 -5
- package/dist/application/ProcessSampling.js +3 -1
- package/dist/application/ReconstructionCoverageService.js +2 -1
- package/dist/application/ReconstructionObligationLedgerService.js +2 -1
- package/dist/application/ReferenceSourceImportEntries.js +2 -0
- package/dist/application/ReferenceSourceImportPolicy.js +4 -2
- package/dist/application/ReferenceSourceVcsAdapter.js +35 -4
- package/dist/application/SessionProviderRouter.js +4 -1
- package/dist/application/Setup.js +1 -128
- package/dist/application/SetupClientConfiguration.js +17 -6
- package/dist/application/SetupHost.js +111 -0
- package/dist/application/SetupRegistrationEnvironment.js +1 -2
- package/dist/application/SetupSkill.js +9 -3
- package/dist/application/SetupTypes.js +17 -0
- package/dist/application/StoreFileLock.js +7 -2
- package/dist/application/SupportedClients.js +8 -0
- package/dist/application/Uninstall.js +9 -4
- package/dist/application/UpdateRuntime.js +5 -2
- package/dist/application/WindowsCapabilities.js +7 -7
- package/dist/application/runtime.js +3 -1
- package/dist/artifacts/ArtifactProvider.js +3 -1
- package/dist/artifacts/DirectoryArtifactReader.js +2 -0
- package/dist/artifacts/NativeDmgArtifactReader.js +10 -3
- package/dist/artifacts/NibArchive.js +4 -2
- package/dist/artifacts/SafeOutputTree.js +26 -10
- package/dist/artifacts/ZipArtifactReader.js +1 -0
- package/dist/browser/BrowserProcessStartup.js +3 -1
- package/dist/browser/CdpAuthorizedMainFrame.js +1 -1
- package/dist/browser/CdpBrowserProvider.js +4 -1
- package/dist/browser/CdpCaptureDocuments.js +3 -1
- package/dist/browser/CdpCaptureEventHandlers.js +6 -2
- package/dist/browser/CdpCaptureStorageFingerprints.js +1 -1
- package/dist/browser/CdpCaptureValues.js +6 -2
- package/dist/browser/CdpConnection.js +8 -6
- package/dist/browser/CdpElectronInspection.js +3 -3
- package/dist/browser/CdpElectronProvider.js +4 -1
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpEndpoint.js +22 -10
- package/dist/browser/CdpObservationSession.js +2 -1
- package/dist/browser/CdpOptionalCommand.js +1 -1
- package/dist/browser/CdpPageCapture.js +2 -1
- package/dist/browser/CdpSafeMetadata.js +53 -8
- package/dist/browser/CdpScreenshot.js +1 -1
- package/dist/browser/CdpTargetSession.js +8 -5
- package/dist/browser/CdpWebMcpDiscovery.js +1 -1
- package/dist/browser/ElectronFileScope.js +9 -3
- package/dist/browser/JavaScriptRuntimeScope.js +3 -1
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +3 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +1 -1
- package/dist/browser/PlaywrightElectronActiveProvider.js +6 -2
- package/dist/browser/PlaywrightExecutionBoundary.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +10 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +3 -1
- package/dist/browser/PlaywrightScenarioEvents.js +6 -2
- package/dist/browser/PlaywrightScenarioSession.js +5 -2
- package/dist/browser/V8InspectorEndpoint.js +2 -1
- package/dist/browser/V8InspectorProvider.js +6 -1
- package/dist/browser/WebSourceMapFetcher.js +24 -11
- package/dist/cli/androidCommands.js +81 -0
- package/dist/{cliApplicationCommands.js → cli/applicationCommands.js} +18 -16
- package/dist/{cliBrowserAdvancedCommands.js → cli/browserAdvancedCommands.js} +13 -16
- package/dist/{cliBrowserCommands.js → cli/browserCommands.js} +9 -9
- package/dist/cli/commandCancellation.js +24 -0
- package/dist/cli/coreAnalysisCommands.js +110 -17
- package/dist/{cliElectronCommands.js → cli/electronCommands.js} +14 -13
- package/dist/cli/firmwareCommands.js +75 -0
- package/dist/{cliSetup.js → cli/interactiveSetup.js} +1 -1
- package/dist/cli/javascriptApplicationAnalysis.js +1 -1
- package/dist/cli/managedCommands.js +1 -1
- package/dist/cli/managedProjectGraphCommand.js +1 -1
- package/dist/cli/options.js +7 -1
- package/dist/{cliProcessCommands.js → cli/processCommands.js} +3 -3
- package/dist/cli/referenceSourceImportStatus.js +10 -0
- package/dist/cli/setupCommands.js +4 -2
- package/dist/cli/utilityCommands.js +3 -2
- package/dist/cli.js +10 -15
- package/dist/cliBrowserContext.js +1 -1
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +11 -2
- package/dist/cliEvidenceCommands.js +2 -1
- package/dist/cliJavaScriptRuntimeCommands.js +2 -1
- package/dist/cliJsonInput.js +26 -11
- package/dist/cliLogging.js +2 -1
- package/dist/cliOutput.js +15 -16
- package/dist/config/environment.js +11 -1
- package/dist/config/parseConfig.js +7 -1
- package/dist/config/parsers.js +1 -1
- package/dist/contracts/androidToolContracts.js +77 -0
- package/dist/contracts/applicationToolContracts.js +32 -5
- package/dist/contracts/applicationWorkflowInputContracts.js +13 -13
- package/dist/contracts/artifactComparisonExample.js +7 -14
- package/dist/contracts/enhancedToolContracts.js +31 -0
- package/dist/contracts/errorSchemas.js +4 -2
- package/dist/contracts/evidenceInputContracts.js +13 -0
- package/dist/contracts/firmwareToolContracts.js +38 -0
- package/dist/contracts/officialToolContracts.js +66 -0
- package/dist/contracts/promptContracts.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +4 -0
- package/dist/contracts/sessionToolContracts.js +43 -0
- package/dist/contracts/sessionToolSchemas.js +1 -1
- package/dist/contracts/toolContractExamples.js +5 -0
- package/dist/contracts/toolContractTypes.js +2 -0
- package/dist/contracts/toolContracts.js +7 -130
- package/dist/contracts/toolEffects.js +43 -0
- package/dist/contracts/toolOutputSchemaGroups.js +4 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +1 -0
- package/dist/doctorRuntime.js +5 -1
- package/dist/domain/analysisErrorBase.js +33 -0
- package/dist/domain/analysisErrorCore.js +60 -0
- package/dist/domain/analysisErrorPresentation.js +22 -2
- package/dist/domain/analysisErrorProjection.js +24 -3
- package/dist/domain/analysisSnapshot.js +1 -0
- package/dist/domain/androidAnalysis.js +141 -0
- package/dist/domain/appleAssetCatalog.js +1 -1
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/artifactInspection.js +19 -17
- package/dist/domain/artifactInventoryEvidence.js +20 -25
- package/dist/domain/artifactOperationError.js +16 -0
- package/dist/domain/browserObservation.js +12 -4
- package/dist/domain/browserObservationError.js +23 -0
- package/dist/domain/browserScenario.js +1 -1
- package/dist/domain/browserScenarioCapture.js +1 -1
- package/dist/domain/browserScenarioDiff.js +1 -1
- package/dist/domain/browserScenarioNormalization.js +6 -11
- package/dist/domain/browserScenarioValues.js +3 -1
- package/dist/domain/callPath.js +47 -7
- package/dist/domain/canonicalDigest.js +65 -0
- package/dist/domain/canonicalOrdering.js +11 -0
- package/dist/domain/changedBehavior.js +8 -7
- package/dist/domain/comparisonSemantics.js +2 -4
- package/dist/domain/configurationErrors.js +25 -0
- package/dist/domain/dosCom.js +8 -0
- package/dist/domain/electronActiveObservation.js +3 -1
- package/dist/domain/electronStaticAnalysisBrowser.js +13 -23
- package/dist/domain/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/electronStaticAnalysisValues.js +23 -3
- package/dist/domain/evidence.js +3 -11
- package/dist/domain/evidenceErrors.js +30 -0
- package/dist/domain/firmwareAnalysis.js +121 -0
- package/dist/domain/functionComparison.js +4 -2
- package/dist/domain/functionComparisonDimensions.js +6 -4
- package/dist/domain/functionComparisonNormalization.js +8 -1
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/hopperErrors.js +78 -0
- package/dist/domain/hopperValues.js +2 -1
- package/dist/domain/interfaceBuilderGraph.js +3 -1
- package/dist/domain/javascriptApplicationChangeGraph.js +2 -2
- package/dist/domain/javascriptApplicationGraph.js +13 -22
- package/dist/domain/javascriptApplicationVersionComparison.js +3 -11
- package/dist/domain/javascriptApplicationVersionItems.js +3 -3
- package/dist/domain/javascriptApplicationVersionKeys.js +1 -1
- package/dist/domain/javascriptAstFingerprint.js +1 -1
- package/dist/domain/javascriptExportShapeComparison.js +1 -2
- package/dist/domain/javascriptExportShapeSelection.js +1 -1
- package/dist/domain/javascriptExportShapeVariants.js +7 -3
- package/dist/domain/javascriptFeatureSeed.js +29 -9
- package/dist/domain/javascriptFeatureTrace.js +9 -13
- package/dist/domain/javascriptFeatureTraversal.js +2 -1
- package/dist/domain/javascriptNativeHandoff.js +2 -1
- package/dist/domain/javascriptRuntimeLoadState.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationActive.js +3 -10
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +4 -3
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +8 -14
- package/dist/domain/javascriptRuntimeReconciliationResult.js +4 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +5 -2
- package/dist/domain/javascriptRuntimeStaticCandidates.js +8 -4
- package/dist/domain/javascriptSemanticAnalysis.js +40 -3
- package/dist/domain/javascriptSemanticCallResolution.js +2 -1
- package/dist/domain/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascriptSemanticDataEffects.js +2 -1
- package/dist/domain/javascriptSemanticFingerprints.js +1 -1
- package/dist/domain/javascriptSemanticGraph.js +23 -28
- package/dist/domain/javascriptSemanticPrimitives.js +9 -2
- package/dist/domain/javascriptSemanticProjection.js +2 -1
- package/dist/domain/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascriptSemanticProvenance.js +1 -1
- package/dist/domain/javascriptSemanticQuery.js +7 -8
- package/dist/domain/javascriptSemanticQueryAssessment.js +1 -2
- package/dist/domain/javascriptSemanticQueryIdentity.js +1 -2
- package/dist/domain/javascriptSemanticReturns.js +2 -1
- package/dist/domain/javascriptSemanticValues.js +50 -16
- package/dist/domain/javascriptSourceParser.js +4 -2
- package/dist/domain/javascriptStaticAnalysis.js +1 -1
- package/dist/domain/javascriptStaticAnalysisBundler.js +2 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +14 -6
- package/dist/domain/javascriptStaticAnalysisHelpers.js +31 -4
- package/dist/domain/jsonShape.js +6 -2
- package/dist/domain/managedMemberComparison.js +1 -0
- package/dist/domain/managedMemberComparisonItems.js +2 -0
- package/dist/domain/managedNativeVerificationMatch.js +5 -3
- package/dist/domain/nativeDataType.js +2 -0
- package/dist/domain/nativeFunctionAnnotations.js +43 -0
- package/dist/domain/nativeLoadImage.js +95 -0
- package/dist/domain/nativeMetadataRecovery.js +55 -0
- package/dist/domain/processCapture.js +0 -1
- package/dist/domain/processEvidenceProvider.js +11 -0
- package/dist/domain/processTraceComparison.js +1 -1
- package/dist/domain/providerAdapterError.js +17 -0
- package/dist/domain/providerCleanupError.js +1 -1
- package/dist/domain/providerSelectionError.js +44 -0
- package/dist/domain/reconstructionUnknowns.js +1 -1
- package/dist/domain/reconstructionVerification.js +22 -8
- package/dist/domain/referenceSourceClassification.js +5 -6
- package/dist/domain/referenceSourceGraph.js +9 -17
- package/dist/domain/referenceSourceImportParsing.js +38 -23
- package/dist/domain/runtimeIdentification.js +1 -1
- package/dist/domain/runtimeVersion.js +4 -7
- package/dist/domain/safeJson.js +13 -0
- package/dist/domain/sourceToBundleComparison.js +5 -7
- package/dist/domain/sourceToBundleSignals.js +6 -6
- package/dist/domain/staticRuntimeCorrelation.js +9 -7
- package/dist/domain/unknownRegistryError.js +10 -0
- package/dist/domain/webBundleAnalyzerAst.js +22 -5
- package/dist/domain/webBundleAnalyzerInspection.js +20 -14
- package/dist/dotnet/ManagedMemberRows.js +1 -1
- package/dist/dotnet/ManagedMetadataHeaps.js +3 -2
- package/dist/dotnet/ManagedMetadataInventoryRows.js +4 -2
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -1
- package/dist/dotnet/ManagedStaticProvider.js +3 -1
- package/dist/firmware/FirmwareCommand.js +163 -0
- package/dist/firmware/FirmwareFiles.js +190 -0
- package/dist/firmware/FirmwareProvider.js +258 -0
- package/dist/firmware/FirmwarePublication.js +84 -0
- package/dist/firmware/FirmwareRelease.js +32 -0
- package/dist/firmware/FirmwareReports.js +223 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +5 -5
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -8
- package/dist/ghidra/GhidraClient.js +52 -6
- package/dist/ghidra/GhidraDiagnostics.js +3 -0
- package/dist/ghidra/GhidraDoctor.js +38 -14
- package/dist/ghidra/GhidraFunctionValues.js +10 -4
- package/dist/ghidra/GhidraInstallation.js +10 -4
- package/dist/ghidra/GhidraInventoryValues.js +39 -2
- package/dist/ghidra/GhidraLauncher.js +91 -26
- package/dist/ghidra/GhidraLoadImageValues.js +199 -0
- package/dist/ghidra/GhidraProvider.js +129 -13
- package/dist/ghidra/GhidraProviderCapabilities.js +52 -15
- package/dist/ghidra/GhidraRequestQueue.js +2 -2
- package/dist/ghidra/GhidraSessionError.js +31 -4
- package/dist/ghidra/GhidraSessionValues.js +10 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +16 -2
- package/dist/ghidra/GhidraTransport.js +12 -0
- package/dist/ghidra/extensions/GhidraExtensionFailures.js +20 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +170 -0
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +21 -0
- package/dist/ghidra/extensions/nativeaot/NativeAotReport.js +84 -0
- package/dist/hopper/BridgeLauncher.js +4 -2
- package/dist/hopper/HopperAnalysisProfile.js +7 -2
- package/dist/hopper/HopperCleanup.js +55 -9
- package/dist/hopper/HopperClient.js +14 -4
- package/dist/hopper/HopperProcessDiagnostic.js +1 -1
- package/dist/hopper/HopperProvider.js +8 -4
- package/dist/hopper/HopperRequestQueue.js +7 -3
- package/dist/hopper/HopperSessionValues.js +1 -1
- package/dist/hopper/HopperSocketConnection.js +1 -1
- package/dist/hopper/HopperTargetLease.js +23 -15
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +7 -8
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -2
- package/dist/hopper/protocol.js +8 -8
- package/dist/ida/IdaConfiguration.js +56 -0
- package/dist/ida/IdaDoctor.js +53 -0
- package/dist/ida/IdaInput.js +62 -0
- package/dist/ida/IdaMcpConnection.js +111 -0
- package/dist/ida/IdaOperationRunner.js +299 -0
- package/dist/ida/IdaProtocolValues.js +178 -0
- package/dist/ida/IdaProvider.js +126 -0
- package/dist/ida/IdaProviderCapabilities.js +60 -0
- package/dist/ida/IdaSessionClient.js +306 -0
- package/dist/ida/IdaWorkspace.js +54 -0
- package/dist/main/shutdown.js +21 -1
- package/dist/main/startup.js +1 -1
- package/dist/main/transport.js +8 -4
- package/dist/main.js +5 -2
- package/dist/native/AppleDispatchMetadata.js +31 -10
- package/dist/native/NativeMacOSProvider.js +87 -15
- package/dist/native/NativeMachoInspection.js +42 -12
- package/dist/native/NativeUiHelperRuntime.js +7 -1
- package/dist/native/NativeUiObservation.js +6 -2
- package/dist/native/parsers/demangle.js +1 -1
- package/dist/native/parsers/dyldInfo.js +3 -3
- package/dist/native/parsers/otool.js +4 -1
- package/dist/native/parsers/plist.js +11 -3
- package/dist/process/PrivateRuntimeRoot.js +13 -3
- package/dist/process/ProcessOwnership.js +5 -73
- package/dist/process/ProcessOwnershipObservation.js +62 -2
- package/dist/process/ProcessOwnershipProcessTree.js +13 -0
- package/dist/process/ProviderProcess.js +24 -7
- package/dist/process/ProviderRunLineage.js +1 -1
- package/dist/process/WindowsAuthority.js +20 -1
- package/dist/reference/ReferenceSourceReaderEntries.js +5 -1
- package/dist/reference/ReferenceSourceReaderFile.js +1 -0
- package/dist/server/createServer.js +25 -2
- package/dist/server/mcpProgress.js +2 -1
- package/dist/server/promptCompletion.js +3 -3
- package/dist/server/registerAndroidTools.js +30 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +5 -1
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +7 -2
- package/dist/server/registerApplicationTools/compareVersions.js +5 -1
- package/dist/server/registerApplicationTools/traceFeature.js +7 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +7 -2
- package/dist/server/registerEnhancedTools.js +28 -1
- package/dist/server/registerFirmwareTools.js +22 -0
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools/helpers.js +2 -1
- package/dist/server/registerManagedTools.js +1 -1
- package/dist/server/registerManagedWorkflowTools/evidence.js +1 -1
- package/dist/server/registerOfficialTools.js +4 -1
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerSessionTools.js +3 -1
- package/dist/server/runDerivedOperation.js +1 -1
- package/dist/server/sessionAvailabilityPolicy.js +3 -0
- package/dist/server/sessionEvidence.js +1 -1
- package/dist/server/toolResult.js +2 -1
- package/dist/windows/WindowsNativeLoader.js +108 -0
- package/dist/windows/WindowsOwnedProcess.js +168 -0
- package/dist/windows/WindowsPrivateRuntime.js +137 -0
- package/install.sh +4 -6
- package/native/windows/README.md +102 -0
- package/native/windows/build/manifest.json +9 -0
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +38 -24
- package/scripts/rea.mjs +1 -1
- package/scripts/verify-windows-native-artifact.mjs +39 -0
- package/skills/reverse-engineer-anything/SKILL.md +92 -24
- package/skills/reverse-engineer-anything/references/android-applications.md +31 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +19 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +52 -4
- package/dist/browser/CdpCanonicalJsonDigest.js +0 -9
- package/dist/domain/errors.js +0 -324
package/dist/domain/callPath.js
CHANGED
|
@@ -1,8 +1,48 @@
|
|
|
1
|
-
import { DirectedGraph } from "graphology";
|
|
2
|
-
import { bidirectional } from "graphology-shortest-path/unweighted.js";
|
|
3
1
|
import { callPathInputSchema, callPathResultSchema, parseCallPathAddress, } from "./callPathSchemas.js";
|
|
4
2
|
import { parseFunctionEvidence, } from "./functionDossierEvidence.js";
|
|
5
3
|
export { callPathInputSchema, callPathResultSchema };
|
|
4
|
+
/** Minimal directed caller-to-callee adjacency for call-path search. */
|
|
5
|
+
class CallGraph {
|
|
6
|
+
successors = new Map();
|
|
7
|
+
mergeNode(node) {
|
|
8
|
+
if (!this.successors.has(node))
|
|
9
|
+
this.successors.set(node, new Set());
|
|
10
|
+
}
|
|
11
|
+
mergeDirectedEdge(source, target) {
|
|
12
|
+
this.mergeNode(source);
|
|
13
|
+
this.mergeNode(target);
|
|
14
|
+
this.successors.get(source)?.add(target);
|
|
15
|
+
}
|
|
16
|
+
hasNode(node) {
|
|
17
|
+
return this.successors.has(node);
|
|
18
|
+
}
|
|
19
|
+
outDegree(node) {
|
|
20
|
+
return this.successors.get(node)?.size ?? 0;
|
|
21
|
+
}
|
|
22
|
+
outNeighbors(node) {
|
|
23
|
+
return [...(this.successors.get(node) ?? [])];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Breadth-first shortest depth from start to goal, or null when unreachable. */
|
|
27
|
+
const shortestPathDepth = (graph, start, goal) => {
|
|
28
|
+
if (start === goal)
|
|
29
|
+
return 0;
|
|
30
|
+
const depth = new Map([[start, 0]]);
|
|
31
|
+
const queue = [start];
|
|
32
|
+
for (let index = 0; index < queue.length; index += 1) {
|
|
33
|
+
const node = queue[index] ?? "";
|
|
34
|
+
const next = (depth.get(node) ?? 0) + 1;
|
|
35
|
+
for (const neighbor of graph.outNeighbors(node)) {
|
|
36
|
+
if (neighbor === goal)
|
|
37
|
+
return next;
|
|
38
|
+
if (!depth.has(neighbor)) {
|
|
39
|
+
depth.set(neighbor, next);
|
|
40
|
+
queue.push(neighbor);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
6
46
|
/** Reconstruct direct-callee paths from explicit analyze_function Evidence. */
|
|
7
47
|
export const buildCallPath = (input) => {
|
|
8
48
|
const parsed = callPathInputSchema.parse(input);
|
|
@@ -13,16 +53,16 @@ export const buildCallPath = (input) => {
|
|
|
13
53
|
start: parsed.start.address,
|
|
14
54
|
goal: parsed.goal.address,
|
|
15
55
|
});
|
|
16
|
-
const
|
|
17
|
-
?
|
|
56
|
+
const shortestDepth = graph.hasNode(parsed.start.address) && graph.hasNode(parsed.goal.address)
|
|
57
|
+
? shortestPathDepth(graph, parsed.start.address, parsed.goal.address)
|
|
18
58
|
: null;
|
|
19
|
-
const paths =
|
|
59
|
+
const paths = shortestDepth === null
|
|
20
60
|
? []
|
|
21
61
|
: enumeratePaths({
|
|
22
62
|
graph,
|
|
23
63
|
start: parsed.start.address,
|
|
24
64
|
goal: parsed.goal.address,
|
|
25
|
-
shortestDepth
|
|
65
|
+
shortestDepth,
|
|
26
66
|
}).paths.map((path) => citePath(path, snapshots));
|
|
27
67
|
const shortestHops = paths[0]?.hops;
|
|
28
68
|
const found = shortestHops !== undefined;
|
|
@@ -94,7 +134,7 @@ const assertCompatible = (snapshots) => {
|
|
|
94
134
|
}
|
|
95
135
|
};
|
|
96
136
|
const createGraph = (snapshots) => {
|
|
97
|
-
const graph = new
|
|
137
|
+
const graph = new CallGraph();
|
|
98
138
|
for (const [address, snapshot] of snapshots) {
|
|
99
139
|
graph.mergeNode(address);
|
|
100
140
|
for (const callee of snapshot.collections.callees.items) {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/** Hash canonicalize-compatible JSON without assembling an aggregate string. */
|
|
3
|
+
export const digestCanonicalValue = (value, context = "Comparison") => {
|
|
4
|
+
const hash = createHash("sha256");
|
|
5
|
+
const encoded = emitCanonical(value, (part) => hash.update(part), new Set());
|
|
6
|
+
if (!encoded)
|
|
7
|
+
throw new TypeError(`${context} could not canonicalize data`);
|
|
8
|
+
return hash.digest("hex");
|
|
9
|
+
};
|
|
10
|
+
const emitCanonical = (value, emit, ancestors) => {
|
|
11
|
+
if (typeof value === "number" && !Number.isFinite(value))
|
|
12
|
+
throw new Error(Number.isNaN(value) ? "NaN is not allowed" : "Infinity is not allowed");
|
|
13
|
+
if (value === null || typeof value !== "object") {
|
|
14
|
+
const encoded = JSON.stringify(value);
|
|
15
|
+
if (encoded === undefined)
|
|
16
|
+
return false;
|
|
17
|
+
emit(encoded);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (ancestors.has(value))
|
|
21
|
+
throw new Error("Circular reference detected");
|
|
22
|
+
ancestors.add(value);
|
|
23
|
+
try {
|
|
24
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
25
|
+
const normalized = value.toJSON();
|
|
26
|
+
return emitCanonical(normalized, emit, ancestors);
|
|
27
|
+
}
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
emit("[");
|
|
30
|
+
const length = value.length;
|
|
31
|
+
for (let index = 0; index < length; index += 1) {
|
|
32
|
+
if (index > 0)
|
|
33
|
+
emit(",");
|
|
34
|
+
// Preserve canonicalize's sparse-array and unsupported-value behavior.
|
|
35
|
+
if (!(index in value))
|
|
36
|
+
continue;
|
|
37
|
+
const item = value[index];
|
|
38
|
+
emitCanonical(item === undefined || typeof item === "symbol" ? null : item, emit, ancestors);
|
|
39
|
+
}
|
|
40
|
+
emit("]");
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
emit("{");
|
|
44
|
+
let first = true;
|
|
45
|
+
for (const key of Object.keys(value).sort()) {
|
|
46
|
+
if (Reflect.get(value, key) === undefined ||
|
|
47
|
+
typeof Reflect.get(value, key) === "symbol")
|
|
48
|
+
continue;
|
|
49
|
+
const item = Reflect.get(value, key);
|
|
50
|
+
if (!first)
|
|
51
|
+
emit(",");
|
|
52
|
+
first = false;
|
|
53
|
+
emit(JSON.stringify(key));
|
|
54
|
+
emit(":");
|
|
55
|
+
if (!emitCanonical(item, emit, ancestors))
|
|
56
|
+
emit("undefined");
|
|
57
|
+
}
|
|
58
|
+
emit("}");
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
ancestors.delete(value);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical code-point ordering shared across domain and application layers.
|
|
3
|
+
*
|
|
4
|
+
* Compares strings by Unicode code point (`<`/`>`) so graph ordering,
|
|
5
|
+
* fingerprints, and deterministic tie-breaks stay stable regardless of
|
|
6
|
+
* locale. Prefer this over `String.prototype.localeCompare`, which is
|
|
7
|
+
* locale-dependent.
|
|
8
|
+
*/
|
|
9
|
+
export const compareCodePoints = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
10
|
+
/** Deduplicate and sort strings with canonical code-point ordering. */
|
|
11
|
+
export const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { artifactComparisonResultSchema } from "./artifactComparison.js";
|
|
3
|
+
import { uniqueSorted } from "./canonicalOrdering.js";
|
|
3
4
|
import { evidenceSchema, parseEvidence } from "./evidence.js";
|
|
4
5
|
import { functionComparisonResultSchema } from "./functionComparison.js";
|
|
6
|
+
import { PROCESS_PROVIDER, isProcessEvidenceProvider, } from "./processEvidenceProvider.js";
|
|
5
7
|
import { comparisonStatusSchema, deriveProcessComparisonStatus, PROCESS_COMPARISON_DIMENSIONS, processCaptureComparisonSchema, } from "./processCapture.js";
|
|
6
8
|
import { prefixedDigestSchema } from "./../domain/digests.js";
|
|
7
9
|
const evidenceIdSchema = prefixedDigestSchema("ev");
|
|
@@ -65,9 +67,7 @@ export const changedBehaviorResultSchema = z
|
|
|
65
67
|
const EXPECTED_PROVIDERS = {
|
|
66
68
|
compare_process_captures: {
|
|
67
69
|
predicates: ["rea.process-comparison"],
|
|
68
|
-
|
|
69
|
-
name: "REA deterministic process harness",
|
|
70
|
-
version: "3",
|
|
70
|
+
...PROCESS_PROVIDER,
|
|
71
71
|
},
|
|
72
72
|
compare_artifacts: {
|
|
73
73
|
predicates: ["rea.artifact-comparison"],
|
|
@@ -132,9 +132,11 @@ const parseComparisonEvidence = (input) => {
|
|
|
132
132
|
.parse(evidence.operation);
|
|
133
133
|
const expected = EXPECTED_PROVIDERS[operation];
|
|
134
134
|
if (!acceptsPredicate(expected.predicates, evidence.predicate_type) ||
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
(operation === "compare_process_captures"
|
|
136
|
+
? !isProcessEvidenceProvider(evidence.provider)
|
|
137
|
+
: evidence.provider.id !== expected.id ||
|
|
138
|
+
evidence.provider.name !== expected.name ||
|
|
139
|
+
evidence.provider.version !== expected.version) ||
|
|
138
140
|
evidence.confidence !== "derived" ||
|
|
139
141
|
evidence.authority !== "analyst-inference" ||
|
|
140
142
|
evidence.subject !== null)
|
|
@@ -275,7 +277,6 @@ const count = (findings, classification) => findings.filter((finding) => finding
|
|
|
275
277
|
const compareFindings = (left, right) => [left.scope, left.dimension, left.source_comparison_id]
|
|
276
278
|
.join("\0")
|
|
277
279
|
.localeCompare([right.scope, right.dimension, right.source_comparison_id].join("\0"), "en");
|
|
278
|
-
const uniqueSorted = (values) => [...new Set(values)].sort((left, right) => left.localeCompare(right, "en"));
|
|
279
280
|
const assertUnique = (values, label) => {
|
|
280
281
|
if (new Set(values).size !== values.length)
|
|
281
282
|
throw new TypeError(`Changed-behavior analysis rejects duplicate ${label}`);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import canonicalize from "canonicalize";
|
|
2
|
+
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
3
3
|
/** Whether an inventory can support a claim that an item is absent. */
|
|
4
4
|
export const absenceClaimable = (coverage) => coverage.status === "complete" &&
|
|
5
5
|
coverage.truncated !== true &&
|
|
6
6
|
(coverage.omitted_count === undefined || coverage.omitted_count === 0);
|
|
7
7
|
/** SHA-256 of canonical JSON for stable, provider-neutral comparison IDs. */
|
|
8
8
|
export const canonicalDigest = (value, context = "Comparison") => {
|
|
9
|
-
return
|
|
10
|
-
.update(canonicalJson(value, context))
|
|
11
|
-
.digest("hex");
|
|
9
|
+
return digestCanonicalValue(value, context);
|
|
12
10
|
};
|
|
13
11
|
/** Canonical JSON used for deterministic tie breaking and stable digests. */
|
|
14
12
|
export const canonicalJson = (value, context = "Comparison") => {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AnalysisError } from "./analysisErrorBase.js";
|
|
2
|
+
/** Runtime configuration could not be parsed safely. */
|
|
3
|
+
export class ConfigurationError extends AnalysisError {
|
|
4
|
+
_tag = "ConfigurationError";
|
|
5
|
+
}
|
|
6
|
+
/** No app or binary session exists for an analysis request. */
|
|
7
|
+
export class NoBinaryOpenError extends AnalysisError {
|
|
8
|
+
_tag = "NoBinaryOpenError";
|
|
9
|
+
constructor() {
|
|
10
|
+
super("No app is open. Ask the user which app to investigate, then call open_binary with its local path.");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** A supplied target path could not be safely opened as a supported app or binary. */
|
|
14
|
+
export class BinaryTargetError extends AnalysisError {
|
|
15
|
+
path;
|
|
16
|
+
reason;
|
|
17
|
+
_tag = "BinaryTargetError";
|
|
18
|
+
constraint;
|
|
19
|
+
constructor(path, reason, options) {
|
|
20
|
+
super(`Cannot open artifact: ${reason}`, options);
|
|
21
|
+
this.path = path;
|
|
22
|
+
this.reason = reason;
|
|
23
|
+
this.constraint = options?.constraint;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { err, ok } from "./result.js";
|
|
3
|
+
/** Headerless DOS COM interpretation explicitly selected by the caller. */
|
|
4
|
+
export const executableFormatHintSchema = z.literal("dos-com");
|
|
5
|
+
/** Validate the single 64 KiB COM segment, excluding its 256-byte PSP prefix. */
|
|
6
|
+
export const validateDosComLength = (length) => Number.isSafeInteger(length) && length >= 1 && length <= 0xff00
|
|
7
|
+
? ok(null)
|
|
8
|
+
: err("DOS COM requires 1..65280 file bytes (64 KiB segment minus the 256-byte PSP prefix)");
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
import { boundedExpression, collectContextBridgeMembers, electronStaticValue, objectProperty, } from "./electronStaticAnalysisValues.js";
|
|
3
|
+
import { compareCodePoints } from "./canonicalOrdering.js";
|
|
3
4
|
import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
|
|
4
|
-
import { argumentNode, calleeName,
|
|
5
|
+
import { argumentNode, calleeName, propertyName, range, staticPath, staticPathResolutionContext, } from "./javascriptStaticAnalysisHelpers.js";
|
|
5
6
|
/** Inspect BrowserWindow, contextBridge, and utility-process syntax. */
|
|
6
7
|
export const inspectElectronBrowserNode = (node, context) => {
|
|
7
8
|
if (t.isNewExpression(node))
|
|
@@ -38,29 +39,16 @@ const inspectBrowserWindow = (node, context) => {
|
|
|
38
39
|
});
|
|
39
40
|
};
|
|
40
41
|
const collectWindowOptions = (source, options) => {
|
|
41
|
-
|
|
42
|
+
const lookup = objectProperty(options, "webPreferences");
|
|
43
|
+
if (lookup.status !== "explicit" ||
|
|
44
|
+
!t.isObjectExpression(lookup.property.value))
|
|
42
45
|
return {
|
|
43
|
-
status:
|
|
46
|
+
status: lookup.status === "missing" ? "missing" : "dynamic",
|
|
44
47
|
preferences: [],
|
|
45
48
|
preload: { preload_path: null, preload_resolution_context: null },
|
|
46
|
-
unknown:
|
|
49
|
+
unknown: lookup.status === "missing" ? 0 : 1,
|
|
47
50
|
};
|
|
48
|
-
|
|
49
|
-
if (property === undefined)
|
|
50
|
-
return {
|
|
51
|
-
status: "missing",
|
|
52
|
-
preferences: [],
|
|
53
|
-
preload: { preload_path: null, preload_resolution_context: null },
|
|
54
|
-
unknown: 0,
|
|
55
|
-
};
|
|
56
|
-
if (!t.isObjectExpression(property.value))
|
|
57
|
-
return {
|
|
58
|
-
status: "dynamic",
|
|
59
|
-
preferences: [],
|
|
60
|
-
preload: { preload_path: null, preload_resolution_context: null },
|
|
61
|
-
unknown: 1,
|
|
62
|
-
};
|
|
63
|
-
return collectWebPreferences(source, property.value);
|
|
51
|
+
return collectWebPreferences(source, lookup.property.value);
|
|
64
52
|
};
|
|
65
53
|
const collectWebPreferences = (source, object) => {
|
|
66
54
|
const preferences = [];
|
|
@@ -164,10 +152,12 @@ const inspectUtilityProcess = (node, context) => {
|
|
|
164
152
|
const moduleNode = argumentNode(node.arguments[0]);
|
|
165
153
|
const modulePath = moduleNode === undefined ? undefined : staticPath(moduleNode);
|
|
166
154
|
const options = argumentNode(node.arguments[2]);
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
? staticPath(
|
|
155
|
+
const serviceNameProperty = objectProperty(options, "serviceName");
|
|
156
|
+
const serviceName = serviceNameProperty.status === "explicit"
|
|
157
|
+
? staticPath(serviceNameProperty.property.value)
|
|
170
158
|
: undefined;
|
|
159
|
+
if (serviceNameProperty.status !== "missing" && serviceName === undefined)
|
|
160
|
+
context.accumulator.unknownFindings += 1;
|
|
171
161
|
if (modulePath === undefined)
|
|
172
162
|
context.accumulator.unknownFindings += 1;
|
|
173
163
|
const moduleReference = modulePath === undefined || moduleNode === undefined
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
+
import { compareCodePoints } from "./canonicalOrdering.js";
|
|
2
3
|
import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
|
|
3
|
-
import { argumentNode, calleeName,
|
|
4
|
+
import { argumentNode, calleeName, propertyName, range, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
|
|
4
5
|
/** Inspect JavaScript-side imports and re-exports of native .node addons. */
|
|
5
6
|
export const inspectElectronNativeNode = (node, context) => {
|
|
6
7
|
if (t.isImportDeclaration(node))
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
|
-
import { compareCodePoints
|
|
2
|
+
import { compareCodePoints } from "./canonicalOrdering.js";
|
|
3
|
+
import { semanticStaticPropertyName } from "./javascriptAstValues.js";
|
|
4
|
+
import { propertyName, sourceSlice, } from "./javascriptStaticAnalysisHelpers.js";
|
|
3
5
|
/** Preserve one literal value or the exact inert expression. */
|
|
4
6
|
export const electronStaticValue = (source, node) => {
|
|
5
7
|
const literal = literalValue(node);
|
|
@@ -18,8 +20,26 @@ export const boundedExpression = (source, node) => {
|
|
|
18
20
|
const expression = sourceSlice(source, node).trim();
|
|
19
21
|
return expression === "" ? `[${node.type}]` : expression;
|
|
20
22
|
};
|
|
21
|
-
/**
|
|
22
|
-
export const objectProperty = (object, name) =>
|
|
23
|
+
/** Find the effective explicit property, preserving unresolved overrides. */
|
|
24
|
+
export const objectProperty = (object, name) => {
|
|
25
|
+
if (object === undefined)
|
|
26
|
+
return { status: "missing" };
|
|
27
|
+
if (!t.isObjectExpression(object))
|
|
28
|
+
return { status: "dynamic" };
|
|
29
|
+
for (const property of object.properties.toReversed()) {
|
|
30
|
+
if (t.isSpreadElement(property))
|
|
31
|
+
return { status: "dynamic" };
|
|
32
|
+
const key = semanticStaticPropertyName(property.key, property.computed);
|
|
33
|
+
if (key === "" && !t.isStringLiteral(property.key))
|
|
34
|
+
return { status: "dynamic" };
|
|
35
|
+
if (key !== name)
|
|
36
|
+
continue;
|
|
37
|
+
return t.isObjectProperty(property)
|
|
38
|
+
? { status: "explicit", property }
|
|
39
|
+
: { status: "dynamic" };
|
|
40
|
+
}
|
|
41
|
+
return { status: "missing" };
|
|
42
|
+
};
|
|
23
43
|
export function handlerKind(node) {
|
|
24
44
|
if (node === null || node === undefined)
|
|
25
45
|
return "missing";
|
package/dist/domain/evidence.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import canonicalize from "canonicalize";
|
|
3
1
|
import { z } from "zod";
|
|
2
|
+
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
4
3
|
import { analysisProfileSchema, } from "./analysisProfile.js";
|
|
5
4
|
import { jsonValueSchema } from "./jsonValue.js";
|
|
6
5
|
import { digestSchema } from "./../domain/digests.js";
|
|
@@ -21,6 +20,7 @@ const subjectSchema = z.object({
|
|
|
21
20
|
"elf",
|
|
22
21
|
"pe",
|
|
23
22
|
"dos-mz",
|
|
23
|
+
"dos-com",
|
|
24
24
|
"zip",
|
|
25
25
|
"ipa",
|
|
26
26
|
"apk",
|
|
@@ -116,14 +116,6 @@ export const evidenceRecordSchema = z.union([
|
|
|
116
116
|
profiledEvidenceSchema,
|
|
117
117
|
evidenceBaseSchema,
|
|
118
118
|
]);
|
|
119
|
-
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
120
|
-
/** Serialize JSON according to RFC 8785 JSON Canonicalization Scheme. */
|
|
121
|
-
const canonicalJson = (value) => {
|
|
122
|
-
const serialized = canonicalize(value);
|
|
123
|
-
if (serialized === undefined)
|
|
124
|
-
throw new TypeError("RFC 8785 canonicalization rejected a JSON value");
|
|
125
|
-
return serialized;
|
|
126
|
-
};
|
|
127
119
|
const semanticProjection = (evidence) => ({
|
|
128
120
|
subject: evidence.subject === null
|
|
129
121
|
? null
|
|
@@ -149,7 +141,7 @@ const semanticProjection = (evidence) => ({
|
|
|
149
141
|
evidence_links: evidence.evidence_links,
|
|
150
142
|
});
|
|
151
143
|
/** Recompute the semantic identifier, excluding paths and raw payload bytes. */
|
|
152
|
-
const computeEvidenceId = (evidence) => `ev_${
|
|
144
|
+
const computeEvidenceId = (evidence) => `ev_${digestCanonicalValue(semanticProjection(evidence), "Evidence")}`;
|
|
153
145
|
/** Parse evidence and reject a syntactically valid but tampered semantic ID. */
|
|
154
146
|
export const parseEvidence = (input) => {
|
|
155
147
|
const evidence = evidenceRecordSchema.parse(input);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AnalysisError } from "./analysisErrorBase.js";
|
|
2
|
+
/** Evidence identity, schema, or bundle manifests failed integrity checks. */
|
|
3
|
+
export class EvidenceIntegrityError extends AnalysisError {
|
|
4
|
+
_tag = "EvidenceIntegrityError";
|
|
5
|
+
}
|
|
6
|
+
/** A session Evidence reference is missing or has the wrong semantic identity. */
|
|
7
|
+
export class EvidenceReferenceError extends EvidenceIntegrityError {
|
|
8
|
+
evidenceId;
|
|
9
|
+
reason;
|
|
10
|
+
expected;
|
|
11
|
+
actual;
|
|
12
|
+
constructor(evidenceId, reason, expected, actual) {
|
|
13
|
+
super(`Evidence reference ${reason}: ${evidenceId}`);
|
|
14
|
+
this.evidenceId = evidenceId;
|
|
15
|
+
this.reason = reason;
|
|
16
|
+
this.expected = expected;
|
|
17
|
+
this.actual = actual;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Evidence bundle filesystem access failed within the configured policy. */
|
|
21
|
+
export class EvidenceFileError extends AnalysisError {
|
|
22
|
+
operation;
|
|
23
|
+
reason;
|
|
24
|
+
_tag = "EvidenceFileError";
|
|
25
|
+
constructor(operation, reason, options) {
|
|
26
|
+
super(`Evidence bundle ${operation} failed: ${reason}`, options);
|
|
27
|
+
this.operation = operation;
|
|
28
|
+
this.reason = reason;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { digestSchema } from "./digests.js";
|
|
3
|
+
import { jsonValueSchema } from "./jsonValue.js";
|
|
4
|
+
const bytes = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
5
|
+
const range = z.strictObject({ offset: bytes, length: bytes.positive() });
|
|
6
|
+
const target = {
|
|
7
|
+
path: z.string().min(1).describe("Local firmware file; never executed"),
|
|
8
|
+
};
|
|
9
|
+
/** Explicit firmware inspection and extraction intent, independent of engines. */
|
|
10
|
+
export const firmwareInputSchemas = {
|
|
11
|
+
inspect_firmware_regions: z.strictObject(target),
|
|
12
|
+
extract_firmware: z.strictObject({
|
|
13
|
+
...target,
|
|
14
|
+
output_directory: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.describe("Absolute, absent output directory; parent must exist"),
|
|
18
|
+
range: range
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Explicit file-byte interval; omit to extract the whole file"),
|
|
21
|
+
max_depth: z
|
|
22
|
+
.number()
|
|
23
|
+
.int()
|
|
24
|
+
.min(1)
|
|
25
|
+
.max(10)
|
|
26
|
+
.default(3)
|
|
27
|
+
.describe("Extraction depth; reaching it yields partial analysis"),
|
|
28
|
+
max_output_bytes: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.min(1)
|
|
32
|
+
.max(512 * 1024 * 1024)
|
|
33
|
+
.default(256 * 1024 * 1024)
|
|
34
|
+
.describe("Staging file-byte budget, checked during extraction; transient overshoot is possible"),
|
|
35
|
+
max_output_files: z
|
|
36
|
+
.number()
|
|
37
|
+
.int()
|
|
38
|
+
.min(1)
|
|
39
|
+
.max(100_000)
|
|
40
|
+
.default(10_000)
|
|
41
|
+
.describe("Staging entry budget, including directories and links"),
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
/** Validate the operation with its exact input contract. */
|
|
45
|
+
export const firmwareRequestSchema = z.discriminatedUnion("operation", [
|
|
46
|
+
z.strictObject({
|
|
47
|
+
operation: z.literal("inspect_firmware_regions"),
|
|
48
|
+
input: firmwareInputSchemas.inspect_firmware_regions,
|
|
49
|
+
}),
|
|
50
|
+
z.strictObject({
|
|
51
|
+
operation: z.literal("extract_firmware"),
|
|
52
|
+
input: firmwareInputSchemas.extract_firmware,
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
55
|
+
const engine = z.strictObject({
|
|
56
|
+
name: z.string(),
|
|
57
|
+
version: z.string(),
|
|
58
|
+
executable_path: z.string(),
|
|
59
|
+
executable_sha256: digestSchema,
|
|
60
|
+
source_revision: z.null(),
|
|
61
|
+
worker_count: z.literal(1),
|
|
62
|
+
});
|
|
63
|
+
const selection = z.strictObject({ ...range.shape, sha256: digestSchema });
|
|
64
|
+
const chunk = z.strictObject({
|
|
65
|
+
input_path: z.string(),
|
|
66
|
+
provider_id: z.string(),
|
|
67
|
+
range,
|
|
68
|
+
handler: z.string().nullable(),
|
|
69
|
+
encrypted: z.boolean().nullable(),
|
|
70
|
+
root_file_range: range.nullable(),
|
|
71
|
+
});
|
|
72
|
+
/** Portable results retain reported boundaries, unknowns and extraction lineage. */
|
|
73
|
+
export const firmwareResultSchemas = {
|
|
74
|
+
inspect_firmware_regions: z.strictObject({
|
|
75
|
+
engine,
|
|
76
|
+
input_size: bytes,
|
|
77
|
+
regions: z.array(z.strictObject({
|
|
78
|
+
provider_id: z.string(),
|
|
79
|
+
offset: bytes,
|
|
80
|
+
reported_size: bytes,
|
|
81
|
+
signature: z.string(),
|
|
82
|
+
description: z.string(),
|
|
83
|
+
reported_confidence: z.number().int().min(0).max(255),
|
|
84
|
+
size_basis: z.literal("provider_reported_validation_unknown"),
|
|
85
|
+
})),
|
|
86
|
+
coverage: z.literal("signature_scan"),
|
|
87
|
+
}),
|
|
88
|
+
extract_firmware: z.strictObject({
|
|
89
|
+
engine,
|
|
90
|
+
selection,
|
|
91
|
+
output_directory: z.string(),
|
|
92
|
+
coverage: z.enum(["complete", "partial"]),
|
|
93
|
+
files: z.array(z.strictObject({
|
|
94
|
+
relative_path: z.string(),
|
|
95
|
+
path: z.string(),
|
|
96
|
+
size: bytes,
|
|
97
|
+
sha256: digestSchema,
|
|
98
|
+
reported_sha256: digestSchema.nullable(),
|
|
99
|
+
mime_type: z.string().nullable(),
|
|
100
|
+
analysis_depth: bytes.nullable(),
|
|
101
|
+
runtime_address: z.null(),
|
|
102
|
+
original_file_range: z.null(),
|
|
103
|
+
})),
|
|
104
|
+
unpublished_entries: z.array(z.strictObject({
|
|
105
|
+
relative_path: z.string(),
|
|
106
|
+
kind: z.enum(["symlink", "special"]),
|
|
107
|
+
link_target: z.string().nullable(),
|
|
108
|
+
})),
|
|
109
|
+
chunks: z.array(chunk),
|
|
110
|
+
derivations: z.array(z.strictObject({
|
|
111
|
+
parent_path: z.string(),
|
|
112
|
+
child_path: z.string(),
|
|
113
|
+
provider_blob_id: z.string(),
|
|
114
|
+
handler: z.string().nullable(),
|
|
115
|
+
parent_file_range: range.nullable(),
|
|
116
|
+
})),
|
|
117
|
+
depth_limited_paths: z.array(z.string()),
|
|
118
|
+
diagnostics: z.array(jsonValueSchema),
|
|
119
|
+
published_bytes: bytes,
|
|
120
|
+
}),
|
|
121
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { canonicalJson } from "./comparisonSemantics.js";
|
|
1
2
|
import { parseFunctionEvidence } from "./functionDossierEvidence.js";
|
|
2
3
|
import { functionMatch } from "./functionComparisonNormalization.js";
|
|
3
4
|
import { functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
4
|
-
import { overallStatus, summarize
|
|
5
|
+
import { overallStatus, summarize } from "./functionComparisonResults.js";
|
|
5
6
|
import { compareDimensions } from "./functionComparisonDimensions.js";
|
|
6
7
|
export { functionComparisonInputSchema, functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
7
8
|
/** Compare two complete function Evidence records without fuzzy matching. */
|
|
@@ -9,7 +10,8 @@ export const compareFunctions = (leftInput, rightInput) => {
|
|
|
9
10
|
const left = parseFunctionEvidence(leftInput);
|
|
10
11
|
const right = parseFunctionEvidence(rightInput);
|
|
11
12
|
const links = [left.evidence[0].evidence_id, right.evidence[0].evidence_id];
|
|
12
|
-
const providersDiffer = canonicalJson(left.provider) !==
|
|
13
|
+
const providersDiffer = canonicalJson(left.provider, "Function comparison") !==
|
|
14
|
+
canonicalJson(right.provider, "Function comparison");
|
|
13
15
|
const dimensions = compareDimensions(left, right, links, providersDiffer);
|
|
14
16
|
const match = functionMatch(left, right);
|
|
15
17
|
const changes = dimensions.filter(({ status }) => status !== "unchanged");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { canonicalJson } from "./comparisonSemantics.js";
|
|
1
2
|
import { diffLines } from "diff";
|
|
2
3
|
import { commentProjection, combineCoverage, identityProjection, isAutoName, normalizeCfg, project, referenceKindProjection, referenceProjection, sorted, stringAndNameProjection, } from "./functionComparisonNormalization.js";
|
|
3
|
-
import {
|
|
4
|
+
import { dimensionResult, unresolvedDimension as buildUnresolvedDimension, } from "./functionComparisonResults.js";
|
|
4
5
|
const unresolvedDimension = (...[dimension, status, links, leftCount, rightCount, limitations]) => buildUnresolvedDimension({
|
|
5
6
|
dimension,
|
|
6
7
|
status,
|
|
@@ -86,7 +87,8 @@ const compareReferences = (left, right, links, providersDiffer) => {
|
|
|
86
87
|
const rightProjection = referenceProjection(right);
|
|
87
88
|
if (leftProjection.length === 0 && rightProjection.length === 0)
|
|
88
89
|
return compareValues("references", leftProjection, rightProjection, links, true, true, providersDiffer);
|
|
89
|
-
if (canonicalJson(leftProjection) !==
|
|
90
|
+
if (canonicalJson(leftProjection, "Function comparison") !==
|
|
91
|
+
canonicalJson(rightProjection, "Function comparison"))
|
|
90
92
|
return dimensionResult({
|
|
91
93
|
dimension: "references",
|
|
92
94
|
status: "changed",
|
|
@@ -147,8 +149,8 @@ const compareCfg = (left, right, links, providersDiffer) => {
|
|
|
147
149
|
const compareValues = (...[dimension, left, right, links, leftComplete, rightComplete, providersDiffer,]) => {
|
|
148
150
|
if (!leftComplete || !rightComplete)
|
|
149
151
|
return unresolvedDimension(dimension, "unknown", links, null, null, []);
|
|
150
|
-
const leftJson = canonicalJson(left);
|
|
151
|
-
const rightJson = canonicalJson(right);
|
|
152
|
+
const leftJson = canonicalJson(left, "Function comparison");
|
|
153
|
+
const rightJson = canonicalJson(right, "Function comparison");
|
|
152
154
|
return dimensionResult({
|
|
153
155
|
dimension,
|
|
154
156
|
status: leftJson === rightJson ? "unchanged" : "changed",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import canonicalize from "canonicalize";
|
|
2
|
+
import { compareCodePoints } from "./canonicalOrdering.js";
|
|
2
3
|
export const identityProjection = (snapshot) => ({
|
|
3
4
|
name: snapshot.procedure.name,
|
|
4
5
|
signature: snapshot.procedure.signature,
|
|
@@ -128,7 +129,13 @@ export const stringAndNameProjection = (snapshot) => {
|
|
|
128
129
|
? null
|
|
129
130
|
: sorted(values);
|
|
130
131
|
};
|
|
131
|
-
export const sorted = (values) => [...values].sort((left, right) =>
|
|
132
|
+
export const sorted = (values) => [...values].sort((left, right) => {
|
|
133
|
+
const leftJson = canonicalJson(left);
|
|
134
|
+
const rightJson = canonicalJson(right);
|
|
135
|
+
// Preserve existing collation while ordering distinct values within a tie.
|
|
136
|
+
return (leftJson.localeCompare(rightJson) ||
|
|
137
|
+
compareCodePoints(leftJson, rightJson));
|
|
138
|
+
});
|
|
132
139
|
export const combineCoverage = (left, right) => {
|
|
133
140
|
return {
|
|
134
141
|
items: [...left.items, ...right.items],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canonicalDigest
|
|
1
|
+
import { canonicalDigest } from "./comparisonSemantics.js";
|
|
2
2
|
export const dimensionResult = (input) => {
|
|
3
3
|
const context = {
|
|
4
4
|
dimension: input.dimension,
|
|
@@ -54,7 +54,4 @@ export const summarize = (dimensions) => ({
|
|
|
54
54
|
truncated: dimensions.filter(({ status }) => status === "truncated").length,
|
|
55
55
|
unknown: dimensions.filter(({ status }) => status === "unknown").length,
|
|
56
56
|
});
|
|
57
|
-
export const canonicalJson = (value) => {
|
|
58
|
-
return encodeCanonicalJson(value, "Function comparison");
|
|
59
|
-
};
|
|
60
57
|
const digest = (value) => canonicalDigest(value, "Function comparison");
|