rea-agents 3.2.0 → 4.0.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 +183 -332
- package/bridge/ghidra/ReaGhidraBridge.java +561 -74
- package/bridge/hopper_bridge.py +70 -27
- package/bridge/native/ReaNativeUI.swift +157 -0
- package/dist/application/AnalysisContextQueries.js +19 -5
- package/dist/application/AnalysisSnapshotCache.js +30 -11
- package/dist/application/AppleAssetCatalogAnalysis.js +171 -0
- package/dist/application/ArtifactExtractionDestination.js +0 -12
- package/dist/application/ArtifactGraphConstruction.js +44 -11
- package/dist/application/ArtifactInventory/classify.js +7 -15
- package/dist/application/ArtifactInventory/hash.js +4 -2
- package/dist/application/ArtifactInventory/policy.js +2 -17
- package/dist/application/ArtifactInventory/reader.js +3 -3
- package/dist/application/ArtifactInventory/scanCanonical.js +2 -2
- package/dist/application/ArtifactInventory/scanReader.js +12 -4
- package/dist/application/ArtifactInventory/types.js +0 -3
- package/dist/application/BinarySession.js +28 -43
- package/dist/application/BinarySessionExecution.js +37 -1
- package/dist/application/BinaryTargetResolver.js +50 -4
- package/dist/application/BrowserEvidence.js +36 -7
- package/dist/application/BrowserObservationService.js +17 -44
- package/dist/application/BrowserScenarioCaptureService.js +2 -35
- package/dist/application/BrowserScenarioEvidence.js +13 -9
- package/dist/application/CapabilityClientRequirements.js +2 -11
- package/dist/application/CapabilityInventory.js +21 -35
- package/dist/application/ClientConfigurationDocument.js +84 -7
- package/dist/application/ClientRegistrationIdentity.js +32 -0
- package/dist/application/ClientRegistrationStatus.js +59 -6
- package/dist/application/DirectAnalysis.js +37 -58
- package/dist/application/DirectAnalysisStatus.js +4 -4
- package/dist/application/Doctor.js +89 -80
- package/dist/application/DoctorDiagnostics.js +2 -26
- package/dist/application/DoctorScope.js +8 -14
- package/dist/application/ElectronActiveEvidence.js +10 -27
- package/dist/application/ElectronActiveObservationService.js +9 -36
- package/dist/application/ElectronBoundaryAnalysis.js +2 -0
- package/dist/application/ElectronBoundaryGraphNative.js +1 -1
- package/dist/application/ElectronEvidence.js +8 -3
- package/dist/application/ElectronObservationService.js +9 -25
- package/dist/application/EnhancedLiteralTracing.js +4 -8
- package/dist/application/EnhancedTools.js +15 -35
- package/dist/application/FilesystemSnapshot.js +7 -8
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +2 -1
- package/dist/application/JavaScriptApplicationWorkflowService.js +31 -7
- package/dist/application/JavaScriptArtifactAnalysis.js +6 -4
- package/dist/application/JavaScriptArtifactFiles.js +5 -0
- package/dist/application/JavaScriptArtifactPathResolution.js +179 -47
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +6 -3
- package/dist/application/JavaScriptRuntimeObservationService.js +9 -25
- package/dist/application/JavaScriptRuntimeReconciliationService.js +45 -4
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +14 -5
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +27 -6
- package/dist/application/ManagedMemberComparisonService.js +19 -6
- package/dist/application/NativeApiInspection.js +2 -0
- package/dist/application/NativeCallRoutes.js +72 -0
- package/dist/application/NativeDispatchMetadataInspection.js +33 -0
- package/dist/application/NativeUiActionTrace.js +73 -49
- package/dist/application/NativeValueTrace.js +320 -0
- package/dist/application/ProcessCaptureCapability.js +32 -5
- package/dist/application/ProcessCaptureEnvironment.js +9 -26
- package/dist/application/ProcessCaptureError.js +1 -5
- package/dist/application/ProcessCaptureJournal.js +3 -40
- package/dist/application/ProcessCaptureLifecycle.js +102 -111
- package/dist/application/ProcessCli.js +18 -25
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessFilesystemEffects.js +36 -0
- package/dist/application/ProcessHarness.js +41 -120
- package/dist/application/ProcessNormalization.js +2 -17
- package/dist/application/ProcessScenarioRuntimeValidation.js +76 -0
- package/dist/application/ReferenceSourceImport.js +3 -4
- package/dist/application/Setup.js +236 -84
- package/dist/application/SetupClientConfiguration.js +14 -9
- package/dist/application/SetupPlan.js +138 -86
- package/dist/application/SetupSkill.js +0 -1
- package/dist/application/SupportedClients.js +102 -21
- package/dist/application/Uninstall.js +31 -20
- package/dist/application/Update.js +93 -0
- package/dist/application/UpdateMaintenance.js +108 -0
- package/dist/application/UpdateRuntime.js +126 -0
- package/dist/application/runtime.js +13 -2
- package/dist/artifacts/ArtifactPaths.js +6 -8
- package/dist/artifacts/ArtifactProvider.js +94 -41
- package/dist/artifacts/AsarArtifactReader.js +19 -4
- package/dist/artifacts/KeyedArchiveReader.js +110 -0
- package/dist/artifacts/MachOSliceArtifactReader.js +53 -5
- package/dist/artifacts/ZipArtifactReader.js +18 -1
- package/dist/browser/BrowserScenarioSecrets.js +28 -1
- package/dist/browser/CdpBrowserProvider.js +36 -15
- package/dist/browser/CdpCaptureDocuments.js +22 -8
- package/dist/browser/CdpCaptureEventHandlers.js +14 -5
- package/dist/browser/CdpCaptureEventHelpers.js +13 -0
- package/dist/browser/CdpCaptureEvents.js +10 -1
- package/dist/browser/CdpElectronInspection.js +5 -10
- package/dist/browser/CdpElectronProvider.js +1 -5
- package/dist/browser/CdpElectronScripts.js +1 -1
- package/dist/browser/CdpEndpoint.js +3 -2
- package/dist/browser/CdpObservationSession.js +14 -10
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpPageCaptureScripts.js +1 -1
- package/dist/browser/CdpSafeMetadata.js +5 -4
- package/dist/browser/CdpScreenshot.js +16 -5
- package/dist/browser/CdpTargetSession.js +25 -4
- package/dist/browser/CdpWebMcpDiscovery.js +93 -20
- package/dist/browser/JavaScriptRuntimeScope.js +28 -2
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +9 -8
- package/dist/browser/PlaywrightElectronActiveActions.js +3 -10
- package/dist/browser/PlaywrightElectronActiveProvider.js +5 -5
- package/dist/browser/PlaywrightScenarioActions.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +13 -25
- package/dist/browser/PlaywrightScenarioBrowser.js +28 -25
- package/dist/browser/PlaywrightScenarioEvents.js +82 -93
- package/dist/browser/PlaywrightScenarioSession.js +27 -123
- package/dist/browser/PngVisualDiff.js +22 -3
- package/dist/browser/V8InspectorCaptureProjection.js +7 -1
- package/dist/browser/V8InspectorProvider.js +60 -7
- package/dist/browser/WebSourceMapFetcher.js +99 -53
- package/dist/cli/artifactCommands.js +56 -12
- package/dist/cli/coreAnalysisCommands.js +110 -0
- package/dist/cli/managedCommands.js +1 -31
- package/dist/cli/setupCommands.js +16 -14
- package/dist/cli/utilityCommands.js +61 -4
- package/dist/cli.js +5 -7
- package/dist/cliApplicationCommands.js +0 -83
- package/dist/cliBrowserAdvancedCommands.js +7 -11
- package/dist/cliBrowserCommands.js +15 -23
- package/dist/cliBrowserContext.js +3 -24
- package/dist/cliBrowserScenarioCommands.js +2 -10
- package/dist/cliCommandNames.js +82 -7
- package/dist/cliElectronCommands.js +10 -36
- package/dist/cliJavaScriptRuntimeCommands.js +6 -30
- package/dist/cliJsonInput.js +4 -2
- package/dist/cliLogging.js +16 -7
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +2 -4
- package/dist/cliProcessCommands.js +6 -33
- package/dist/cliSetup.js +90 -160
- package/dist/config/environment.js +2 -78
- package/dist/config/parseConfig.js +18 -109
- package/dist/config/parsers.js +0 -23
- package/dist/contracts/applicationToolContracts.js +1 -118
- package/dist/contracts/artifactToolContracts.js +11 -19
- package/dist/contracts/browserScenarioToolContracts.js +1 -5
- package/dist/contracts/browserToolContracts.js +9 -16
- package/dist/contracts/electronToolContracts.js +5 -6
- package/dist/contracts/enhancedInputs.js +3 -2
- package/dist/contracts/errorSchemas.js +16 -40
- package/dist/contracts/functionWorkflowToolContracts.js +2 -2
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +2 -2
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +4 -4
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +1 -1
- package/dist/contracts/managedToolContracts.js +7 -4
- package/dist/contracts/managedWorkflowExamples.js +0 -22
- package/dist/contracts/managedWorkflowToolContracts.js +16 -31
- package/dist/contracts/nativeToolContracts.js +9 -0
- package/dist/contracts/promptContracts.js +6 -6
- package/dist/contracts/sessionToolSchemas.js +3 -3
- package/dist/contracts/toolContractExamples.js +4 -3
- package/dist/contracts/toolContracts.js +18 -7
- package/dist/contracts/toolEffects.js +34 -21
- package/dist/contracts/toolOutputSchemaGroups.js +18 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +9 -6
- package/dist/contracts/toolSchemaMetadata.js +5 -8
- package/dist/doctorRuntime.js +0 -41
- package/dist/domain/analysisErrorPresentation.js +4 -28
- package/dist/domain/analysisErrorProjection.js +33 -50
- package/dist/domain/analysisProfile.js +1 -1
- package/dist/domain/analysisSnapshot.js +77 -3
- package/dist/domain/androidApplication.js +5 -4
- package/dist/domain/appleApplication.js +5 -4
- package/dist/domain/appleAssetCatalog.js +127 -0
- package/dist/domain/artifactComparison.js +7 -11
- package/dist/domain/artifactGraph.js +8 -6
- package/dist/domain/artifactInspection.js +13 -12
- package/dist/domain/binaryTarget.js +23 -9
- package/dist/domain/browserObservation.js +43 -24
- package/dist/domain/browserObservationSchemas.js +2 -1
- package/dist/domain/browserScenario.js +7 -107
- package/dist/domain/browserScenarioCapture.js +0 -1
- package/dist/domain/browserScenarioCaptureValues.js +5 -4
- package/dist/domain/browserScenarioDiff.js +1 -3
- package/dist/domain/browserScenarioValues.js +16 -107
- package/dist/domain/bundleComparison.js +18 -17
- package/dist/domain/callPathSchemas.js +17 -7
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +19 -0
- package/dist/domain/completionLedgerGeneration.js +3 -2
- package/dist/domain/conformancePackage.js +2 -1
- package/dist/domain/conformanceTrustGate.js +3 -5
- package/dist/domain/customProtocolCapture.js +2 -2
- package/dist/domain/digests.js +30 -0
- package/dist/domain/dosMz.js +83 -0
- package/dist/domain/electronActiveObservation.js +7 -5
- package/dist/domain/electronObservation.js +3 -2
- package/dist/domain/electronStaticAnalysisNative.js +15 -6
- package/dist/domain/emptyArraySchema.js +3 -0
- package/dist/domain/errors.js +10 -28
- package/dist/domain/evidence.js +5 -3
- package/dist/domain/evidenceCompletionLedger.js +3 -2
- package/dist/domain/functionComparisonNormalization.js +24 -18
- package/dist/domain/functionComparisonResults.js +3 -7
- package/dist/domain/functionComparisonSchemas.js +3 -2
- package/dist/domain/hopperValues.js +108 -8
- package/dist/domain/javascriptApplicationAnalysis.js +4 -7
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +4 -3
- package/dist/domain/javascriptApplicationGraphSchemas.js +8 -7
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +9 -7
- package/dist/domain/javascriptApplicationVersionItems.js +12 -18
- package/dist/domain/javascriptAstValues.js +4 -0
- package/dist/domain/javascriptExportShapeComparison.js +1 -6
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +6 -10
- package/dist/domain/javascriptExportShapeVariants.js +15 -2
- package/dist/domain/javascriptFeatureTraceSchemas.js +8 -7
- package/dist/domain/javascriptRuntimeObservation.js +14 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +8 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +4 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +6 -4
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +19 -18
- package/dist/domain/javascriptRuntimeStaticCandidates.js +18 -6
- package/dist/domain/javascriptSemanticAnalysis.js +57 -19
- package/dist/domain/javascriptSemanticAsyncEffects.js +39 -40
- package/dist/domain/javascriptSemanticCalls.js +46 -27
- package/dist/domain/javascriptSemanticChildProcesses.js +43 -50
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +91 -18
- package/dist/domain/javascriptSemanticDataEffects.js +22 -10
- package/dist/domain/javascriptSemanticGraphSchemas.js +8 -6
- package/dist/domain/javascriptSemanticObjects.js +13 -3
- package/dist/domain/javascriptSemanticProjection.js +144 -38
- package/dist/domain/javascriptSemanticPromises.js +14 -27
- package/dist/domain/javascriptSemanticQuerySchemas.js +6 -9
- package/dist/domain/javascriptSemanticResources.js +2 -5
- package/dist/domain/javascriptSemanticState.js +4 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +2 -1
- package/dist/domain/javascriptSemanticTraversal.js +13 -5
- package/dist/domain/javascriptSemanticValues.js +10 -9
- package/dist/domain/javascriptSourceParser.js +5 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +8 -5
- package/dist/domain/javascriptStaticAnalysisHelpers.js +16 -7
- package/dist/domain/keyedArchive.js +181 -0
- package/dist/domain/managedApplicationGraph.js +4 -3
- package/dist/domain/managedArtifact.js +2 -1
- package/dist/domain/managedMemberComparison.js +18 -13
- package/dist/domain/managedMemberComparisonCoverage.js +2 -1
- package/dist/domain/managedMemberComparisonItems.js +27 -7
- package/dist/domain/managedMemberComparisonMatch.js +22 -6
- package/dist/domain/managedNativeVerificationMatch.js +2 -2
- package/dist/domain/managedNativeVerificationSchemas.js +7 -5
- package/dist/domain/managedReconstruction.js +6 -5
- package/dist/domain/nativeApiBoundary.js +7 -0
- package/dist/domain/nativeDataType.js +51 -0
- package/dist/domain/nativeInspection.js +0 -1
- package/dist/domain/nativeInstruction.js +82 -0
- package/dist/domain/nativeInvestigationGraph.js +9 -5
- package/dist/domain/nativeUiObservation.js +123 -0
- package/dist/domain/nativeValueFlow.js +17 -0
- package/dist/domain/nativeValueTrace.js +64 -0
- package/dist/domain/objcSwiftMetadata.js +39 -0
- package/dist/domain/peInspection.js +1 -0
- package/dist/domain/processCapture.js +5 -55
- package/dist/domain/processCaptureExample.js +0 -9
- package/dist/domain/processCaptureValidation.js +13 -144
- package/dist/domain/processComparison.js +3 -25
- package/dist/domain/processObservation.js +0 -29
- package/dist/domain/processScenario.js +28 -228
- package/dist/domain/processTraceDimensionProjection.js +0 -15
- package/dist/domain/processTraceEvaluation.js +0 -6
- package/dist/domain/protocolCapture.js +8 -36
- package/dist/domain/reconstructionCoverage.js +3 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +4 -12
- package/dist/domain/reconstructionReadinessSchemas.js +4 -3
- package/dist/domain/reconstructionVerification.js +2 -1
- package/dist/domain/reconstructionVerificationSchemas.js +6 -13
- package/dist/domain/referenceSourceClassification.js +0 -110
- package/dist/domain/referenceSourceGraph.js +15 -5
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/runtimeIdentification.js +6 -5
- package/dist/domain/sourceMapContents.js +5 -0
- package/dist/domain/sourceToBundleComparison.js +3 -10
- package/dist/domain/sourceToBundleComparisonSchemas.js +7 -6
- package/dist/domain/sourceToBundleSignals.js +9 -3
- package/dist/domain/staticRuntimeCorrelation.js +5 -11
- package/dist/domain/webBundleAnalysis.js +17 -9
- package/dist/domain/webBundleAnalyzer.js +1 -1
- package/dist/domain/webCaptureDiff.js +5 -11
- package/dist/domain/webCaptureDiffSchemas.js +2 -1
- package/dist/domain/webMcpDiscovery.js +2 -1
- package/dist/dotnet/ManagedMemberInspectorCore.js +15 -7
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +57 -40
- package/dist/dotnet/ManagedMemberRows.js +2 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +15 -8
- package/dist/dotnet/ManagedPeReader.js +2 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +15 -5
- package/dist/ghidra/GhidraClient.js +38 -8
- package/dist/ghidra/GhidraFunctionValues.js +56 -20
- package/dist/ghidra/GhidraInstallation.js +7 -4
- package/dist/ghidra/GhidraInventoryValues.js +44 -9
- package/dist/ghidra/GhidraLauncher.js +18 -3
- package/dist/ghidra/GhidraProvider.js +23 -2
- package/dist/ghidra/GhidraRequestQueue.js +45 -4
- package/dist/ghidra/GhidraSessionValues.js +5 -0
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperProvider.js +29 -6
- package/dist/hopper/HopperTargetLease.js +18 -4
- package/dist/logger.js +0 -13
- package/dist/main/messages.js +0 -1
- package/dist/main/reload.js +3 -32
- package/dist/main/shutdown.js +1 -2
- package/dist/main/transport.js +0 -17
- package/dist/main.js +0 -10
- package/dist/native/AppleDispatchMetadata.js +582 -0
- package/dist/native/AppleObjcProtocols.js +88 -0
- package/dist/native/AppleSwiftVtables.js +86 -0
- package/dist/native/CommandRunner.js +1 -1
- package/dist/native/NativeHostCapabilities.js +23 -0
- package/dist/native/NativeMacOSProvider.js +61 -9
- package/dist/native/NativeMachoInspection.js +39 -6
- package/dist/native/NativeUiHelperRuntime.js +42 -0
- package/dist/native/NativeUiObservation.js +174 -0
- package/dist/native/parsers/codesign.js +4 -1
- package/dist/native/parsers/dyldInfo.js +51 -25
- package/dist/native/parsers/lipo.js +13 -4
- package/dist/native/parsers/otool.js +84 -39
- package/dist/native/parsers/plist.js +2 -1
- package/dist/process/ExecFileOutput.js +5 -1
- package/dist/process/ProcessOwnership.js +69 -33
- package/dist/process/ProcessOwnershipObservation.js +31 -12
- package/dist/process/ProviderProcess.js +4 -2
- package/dist/reference/ReferenceSourceReaderEntries.js +48 -31
- package/dist/reference/ReferenceSourceReaderErrors.js +24 -0
- package/dist/reference/ReferenceSourceReaderFile.js +11 -5
- package/dist/reference/ReferenceSourceReaderValidate.js +22 -8
- package/dist/server/createServer.js +7 -62
- package/dist/server/registerApplicationTools/helpers.js +2 -9
- package/dist/server/registerApplicationTools.js +0 -4
- package/dist/server/registerArtifactComparisonTool.js +1 -1
- package/dist/server/registerBrowserScenarioTool.js +4 -2
- package/dist/server/registerBrowserTools.js +7 -7
- package/dist/server/registerBundleComparisonTool.js +1 -1
- package/dist/server/registerCloseLifecycleTool.js +1 -1
- package/dist/server/registerElectronTools.js +10 -4
- package/dist/server/registerEnhancedTools.js +20 -12
- package/dist/server/registerEvidenceTools.js +4 -28
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools.js +6 -6
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -2
- package/dist/server/registerManagedTools.js +28 -14
- package/dist/server/registerManagedWorkflowTools.js +0 -2
- package/dist/server/registerProcessComparisonTool.js +1 -3
- package/dist/server/registerSessionRecordTools.js +9 -9
- package/dist/server/registerSessionStatusTool.js +1 -1
- package/dist/server/registerSessionTools.js +28 -57
- package/dist/server/sessionAvailabilityPolicy.js +2 -3
- package/dist/server/sessionToolPolicies.js +0 -4
- package/dist/server/toolResult.js +8 -10
- package/package.json +32 -22
- package/skills/reverse-engineer-anything/SKILL.md +15 -11
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +3 -2
- package/skills/reverse-engineer-anything/references/javascript-applications.md +3 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +8 -6
- package/skills/reverse-engineer-anything/references/runtime-observation.md +15 -11
- package/dist/application/CommandShimReplay.js +0 -152
- package/dist/application/ConfiguredRoots.js +0 -19
- package/dist/application/InstrumentedJavaScriptReplayHost.js +0 -36
- package/dist/application/JavaScriptReplayPermission.js +0 -16
- package/dist/application/JavaScriptReplayPlanning.js +0 -207
- package/dist/application/JavaScriptReplayService.js +0 -274
- package/dist/application/LoopbackReplay.js +0 -389
- package/dist/application/LoopbackReplayRecorder.js +0 -129
- package/dist/application/ManagedRuntimeCorrelationService.js +0 -104
- package/dist/application/NodeRuntimeCharacterizationService.js +0 -191
- package/dist/application/PermissionAuthority.js +0 -268
- package/dist/application/PermissionConfiguration.js +0 -26
- package/dist/application/PermissionFailure.js +0 -5
- package/dist/application/ProcessCaptureAuthority.js +0 -24
- package/dist/application/ProcessCapturePermission.js +0 -13
- package/dist/application/ProcessCheckpoints.js +0 -178
- package/dist/application/ProcessReactiveCoordinator.js +0 -223
- package/dist/application/ProcessReactiveEffects.js +0 -153
- package/dist/application/ProcessReactiveHarness.js +0 -106
- package/dist/application/ProcessReactiveObservations.js +0 -105
- package/dist/application/ProjectPermissionStore.js +0 -199
- package/dist/application/RuntimeExecutableDiagnostics.js +0 -198
- package/dist/application/Upgrade.js +0 -134
- package/dist/browser/SensitiveTextCapture.js +0 -8
- package/dist/cliPolicyCommands.js +0 -185
- package/dist/config/browserScenario.js +0 -77
- package/dist/config/electronAutomation.js +0 -35
- package/dist/config/javascriptReplay.js +0 -41
- package/dist/config/managedRuntime.js +0 -25
- package/dist/config/passiveObservation.js +0 -87
- package/dist/config/permissions.js +0 -23
- package/dist/config/processCapture.js +0 -47
- package/dist/contracts/replayMachineExample.js +0 -37
- package/dist/domain/javascriptExportInstrumentation.js +0 -95
- package/dist/domain/javascriptReplay.js +0 -360
- package/dist/domain/managedRuntimeCorrelation.js +0 -181
- package/dist/domain/nodeRuntimeCharacterization.js +0 -63
- package/dist/domain/permissionPolicy.js +0 -176
- package/dist/domain/processCaptureReactiveSchema.js +0 -68
- package/dist/domain/processCaptureReactiveValidation.js +0 -180
- package/dist/domain/processReactiveCheckpointDataflow.js +0 -32
- package/dist/domain/processReactiveMatching.js +0 -196
- package/dist/domain/processReactiveRuntime.js +0 -116
- package/dist/domain/processReactiveScenario.js +0 -296
- package/dist/domain/processReactiveScenarioPreflight.js +0 -95
- package/dist/domain/processReactiveTransition.js +0 -187
- package/dist/domain/replayMachine.js +0 -320
- package/dist/domain/replayMachineRun.js +0 -168
- package/dist/domain/replayMachineRuntime.js +0 -296
- package/dist/domain/replayMachineValues.js +0 -84
- package/dist/domain/runtimeCharacterization.js +0 -84
- package/dist/replay/JavaScriptReplayWorker.js +0 -382
- package/dist/replay/JavaScriptReplayWorkerTypes.js +0 -1
- package/dist/replay/LinuxJavaScriptReplayRunner.js +0 -216
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -121
- package/dist/replay/LinuxRuntimeClosure.js +0 -44
- package/dist/replay/LinuxSeccompPolicy.js +0 -40
- package/dist/replay/ReplayOutcome.js +0 -104
- package/dist/replay/ReplayProcessLifecycle.js +0 -96
- package/dist/replay/ReplaySeccompFile.js +0 -29
- package/dist/replay/ReplayWorkerProtocol.js +0 -58
- package/dist/replay/SystemJavaScriptReplayHost.js +0 -153
- package/dist/server/ProcessCaptureElicitation.js +0 -153
- package/dist/server/registerApplicationTools/characterization.js +0 -46
- package/dist/server/registerApplicationTools/controlledReplay.js +0 -31
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +0 -29
- package/dist/server/registerReplayMachineTool.js +0 -14
- package/skills/reverse-engineer-anything/references/controlled-replay.md +0 -12
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat } from "node:fs/promises";
|
|
3
|
+
import { DirectoryArtifactReader } from "../artifacts/DirectoryArtifactReader.js";
|
|
4
|
+
import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
|
|
5
|
+
import { analyzeInterfaceBuilderBundle } from "./InterfaceBuilderAnalysis.js";
|
|
6
|
+
import { appleAssetCatalogInputSchema, parseAppleAssetCatalogRecords, projectAppleAssetCatalogPage, } from "../domain/appleAssetCatalog.js";
|
|
7
|
+
import { execFileOutput } from "../process/ExecFileOutput.js";
|
|
8
|
+
const ASSETUTIL = "/usr/bin/assetutil";
|
|
9
|
+
const MAX_CATALOG_BYTES = 64 * 1024 * 1024;
|
|
10
|
+
const MAX_TOTAL_METADATA_BYTES = 64 * 1024 * 1024;
|
|
11
|
+
const RESOURCE_KEY_FIELDS = new Set([
|
|
12
|
+
"image",
|
|
13
|
+
"imageName",
|
|
14
|
+
"image_name",
|
|
15
|
+
"resourceName",
|
|
16
|
+
"resource_name",
|
|
17
|
+
"assetName",
|
|
18
|
+
"asset_name",
|
|
19
|
+
"UIImageName",
|
|
20
|
+
"NSImageName",
|
|
21
|
+
]);
|
|
22
|
+
/** Inspect compiled asset catalog metadata without extracting rendition bytes. */
|
|
23
|
+
export const analyzeAppleAssetCatalogs = async (input) => {
|
|
24
|
+
if (process.platform !== "darwin" && input.runAssetUtil === undefined)
|
|
25
|
+
throw new ArtifactReaderFailure("unavailable", "Apple asset catalog inspection requires macOS assetutil");
|
|
26
|
+
const page = appleAssetCatalogInputSchema.parse(input.page ?? {});
|
|
27
|
+
const reader = new DirectoryArtifactReader(input.bundlePath);
|
|
28
|
+
const catalogs = [];
|
|
29
|
+
let totalMetadataBytes = 0;
|
|
30
|
+
try {
|
|
31
|
+
for await (const entry of reader.entries(input.signal)) {
|
|
32
|
+
if (entry.kind !== "file" || !entry.path.endsWith("Assets.car"))
|
|
33
|
+
continue;
|
|
34
|
+
const inspected = await inspectAssetCatalogEntry({
|
|
35
|
+
reader,
|
|
36
|
+
entry,
|
|
37
|
+
runAssetUtil: input.runAssetUtil ?? runAssetUtil,
|
|
38
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
39
|
+
});
|
|
40
|
+
totalMetadataBytes += inspected.metadataBytes;
|
|
41
|
+
if (totalMetadataBytes > MAX_TOTAL_METADATA_BYTES)
|
|
42
|
+
throw new ArtifactReaderFailure("limit", `Combined asset catalog metadata exceeds ${MAX_TOTAL_METADATA_BYTES} bytes`);
|
|
43
|
+
catalogs.push(inspected.catalog);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await reader.close();
|
|
48
|
+
}
|
|
49
|
+
if (catalogs.length === 0)
|
|
50
|
+
throw new ArtifactReaderFailure("unavailable", "No compiled Assets.car catalogs were found in the app bundle");
|
|
51
|
+
const interfaceBuilder = await analyzeInterfaceBuilderBundle({
|
|
52
|
+
bundlePath: input.bundlePath,
|
|
53
|
+
targetSha256: input.targetSha256,
|
|
54
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
55
|
+
});
|
|
56
|
+
const resourceReferences = collectInterfaceBuilderResourceKeys(interfaceBuilder.graph.nodes);
|
|
57
|
+
const result = projectAppleAssetCatalogPage({
|
|
58
|
+
targetSha256: input.targetSha256,
|
|
59
|
+
catalogs,
|
|
60
|
+
offset: page.offset,
|
|
61
|
+
limit: page.limit,
|
|
62
|
+
resourceReferences,
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
...result,
|
|
66
|
+
limitations: [
|
|
67
|
+
...result.limitations,
|
|
68
|
+
"Exact resource-key joins use only recognized image or asset key fields on decoded Interface Builder resource objects; other archive resource references are not inferred.",
|
|
69
|
+
...(interfaceBuilder.graph.truncated
|
|
70
|
+
? [
|
|
71
|
+
"Interface Builder resource-key joins may be incomplete because the decoded UI graph was truncated.",
|
|
72
|
+
]
|
|
73
|
+
: []),
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const inspectAssetCatalogEntry = async (input) => {
|
|
78
|
+
const { entry, reader, signal } = input;
|
|
79
|
+
const sha256 = await digestBounded(reader, entry, signal);
|
|
80
|
+
const before = await lstat(entry.adapterKey);
|
|
81
|
+
if (entry.sourceIdentity === undefined ||
|
|
82
|
+
before.dev !== entry.sourceIdentity.device ||
|
|
83
|
+
before.ino !== entry.sourceIdentity.inode)
|
|
84
|
+
throw new ArtifactReaderFailure("integrity", `Asset catalog changed before inspection: ${entry.path}`);
|
|
85
|
+
const output = await input.runAssetUtil(entry.adapterKey, signal);
|
|
86
|
+
const after = await lstat(entry.adapterKey);
|
|
87
|
+
if (before.dev !== after.dev ||
|
|
88
|
+
before.ino !== after.ino ||
|
|
89
|
+
before.size !== after.size ||
|
|
90
|
+
(await digestBounded(reader, entry, signal)) !== sha256)
|
|
91
|
+
throw new ArtifactReaderFailure("integrity", `Asset catalog changed during inspection: ${entry.path}`);
|
|
92
|
+
let parsed;
|
|
93
|
+
try {
|
|
94
|
+
parsed = JSON.parse(output);
|
|
95
|
+
}
|
|
96
|
+
catch (cause) {
|
|
97
|
+
throw new ArtifactReaderFailure("format", `assetutil returned invalid JSON for ${entry.path}`, { cause });
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return {
|
|
101
|
+
catalog: {
|
|
102
|
+
path: entry.path,
|
|
103
|
+
sha256,
|
|
104
|
+
records: parseAppleAssetCatalogRecords(parsed),
|
|
105
|
+
},
|
|
106
|
+
metadataBytes: Buffer.byteLength(output, "utf8"),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (cause) {
|
|
110
|
+
throw new ArtifactReaderFailure("format", `assetutil returned an unsupported record for ${entry.path}`, { cause });
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
/** Return only explicit image or asset fields from decoded resource objects. */
|
|
114
|
+
export const collectInterfaceBuilderResourceKeys = (nodes) => nodes.flatMap((node) => {
|
|
115
|
+
const source = node.evidence.find((item) => item.artifact_path !== null && item.artifact_sha256 !== null);
|
|
116
|
+
const sourcePath = source?.artifact_path;
|
|
117
|
+
const sourceArchiveSha256 = source?.artifact_sha256;
|
|
118
|
+
if (sourcePath == null || sourceArchiveSha256 == null)
|
|
119
|
+
return [];
|
|
120
|
+
return Object.entries(node.attributes).flatMap(([field, value]) => RESOURCE_KEY_FIELDS.has(field) &&
|
|
121
|
+
typeof value === "string" &&
|
|
122
|
+
value.length > 0
|
|
123
|
+
? [
|
|
124
|
+
{
|
|
125
|
+
sourceNodeId: node.id,
|
|
126
|
+
sourcePath,
|
|
127
|
+
sourceArchiveSha256,
|
|
128
|
+
field,
|
|
129
|
+
key: value,
|
|
130
|
+
},
|
|
131
|
+
]
|
|
132
|
+
: []);
|
|
133
|
+
});
|
|
134
|
+
const runAssetUtil = async (path, signal) => {
|
|
135
|
+
try {
|
|
136
|
+
return (await execFileOutput(ASSETUTIL, ["--info", path], {
|
|
137
|
+
timeout: 60_000,
|
|
138
|
+
maxBuffer: MAX_CATALOG_BYTES,
|
|
139
|
+
...(signal === undefined ? {} : { signal }),
|
|
140
|
+
})).stdout;
|
|
141
|
+
}
|
|
142
|
+
catch (cause) {
|
|
143
|
+
if (signal?.aborted === true)
|
|
144
|
+
throw new ArtifactReaderFailure("cancelled", "Asset catalog inspection cancelled");
|
|
145
|
+
const code = typeof cause === "object" && cause !== null && "code" in cause
|
|
146
|
+
? cause.code
|
|
147
|
+
: undefined;
|
|
148
|
+
throw new ArtifactReaderFailure(code === "ENOENT"
|
|
149
|
+
? "unavailable"
|
|
150
|
+
: code === "ETIMEDOUT" || code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER"
|
|
151
|
+
? "limit"
|
|
152
|
+
: "io", `assetutil failed${code === undefined ? "" : ` (${String(code)})`}`, { cause });
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const digestBounded = async (reader, entry, signal) => {
|
|
156
|
+
if (entry.declaredSize === null || entry.declaredSize > MAX_CATALOG_BYTES)
|
|
157
|
+
throw new ArtifactReaderFailure("limit", `Asset catalog exceeds ${MAX_CATALOG_BYTES} bytes: ${entry.path}`);
|
|
158
|
+
const stream = await reader.open(entry, signal);
|
|
159
|
+
const hash = createHash("sha256");
|
|
160
|
+
let length = 0;
|
|
161
|
+
for await (const chunk of stream) {
|
|
162
|
+
if (signal?.aborted === true)
|
|
163
|
+
throw new ArtifactReaderFailure("cancelled", "Asset catalog inspection cancelled");
|
|
164
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
165
|
+
length += bytes.length;
|
|
166
|
+
if (length > MAX_CATALOG_BYTES)
|
|
167
|
+
throw new ArtifactReaderFailure("limit", `Asset catalog exceeds byte limit: ${entry.path}`);
|
|
168
|
+
hash.update(bytes);
|
|
169
|
+
}
|
|
170
|
+
return hash.digest("hex");
|
|
171
|
+
};
|
|
@@ -3,15 +3,3 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
/** Choose a fresh temporary destination for an artifact extraction. */
|
|
5
5
|
export const createArtifactExtractionDestination = () => join(tmpdir(), `rea-extracted-${randomUUID()}`);
|
|
6
|
-
/** Stable parent scope used to authorize REA-owned extraction destinations. */
|
|
7
|
-
export const artifactExtractionPermissionRoot = () => tmpdir();
|
|
8
|
-
/** Stable filesystem scope for the destination selected internally by REA. */
|
|
9
|
-
export const artifactExtractionPermissionRequest = () => ({
|
|
10
|
-
capability: "artifact_extract",
|
|
11
|
-
roots: [artifactExtractionPermissionRoot()],
|
|
12
|
-
executables: [],
|
|
13
|
-
environment_names: [],
|
|
14
|
-
network: "none",
|
|
15
|
-
mount: false,
|
|
16
|
-
operation_identity: "extract_artifact:temporary_output",
|
|
17
|
-
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
3
|
import { zipPackageFormatForPath } from "../domain/zipPackageFormat.js";
|
|
4
|
+
import { mzWindowsHeaderOffset, parseDosMzHeader } from "../domain/dosMz.js";
|
|
4
5
|
/** Index the first occurrence for each canonical logical path. */
|
|
5
6
|
export const indexOccurrencesByPath = (occurrences) => {
|
|
6
7
|
const byPath = new Map();
|
|
@@ -25,6 +26,15 @@ export const createOccurrence = (entry, path, parent) => ({
|
|
|
25
26
|
: { offset: entry.byteOffset, length: entry.declaredSize },
|
|
26
27
|
limitations: [...entry.limitations],
|
|
27
28
|
});
|
|
29
|
+
/** Preserve collation order and break distinct-name ties by UTF-16 code units. */
|
|
30
|
+
export const compareDirectoryChildNames = (left, right) => {
|
|
31
|
+
const collated = left.localeCompare(right);
|
|
32
|
+
if (collated !== 0)
|
|
33
|
+
return collated;
|
|
34
|
+
if (left < right)
|
|
35
|
+
return -1;
|
|
36
|
+
return left > right ? 1 : 0;
|
|
37
|
+
};
|
|
28
38
|
export const materializeDirectoryNodes = (occurrences, nodes) => {
|
|
29
39
|
const directories = occurrences
|
|
30
40
|
.filter(({ entry_kind: kind }) => kind === "directory")
|
|
@@ -42,11 +52,12 @@ export const materializeDirectoryNodes = (occurrences, nodes) => {
|
|
|
42
52
|
for (const directory of directories) {
|
|
43
53
|
const children = (childrenByParent.get(directory.occurrence_id) ?? [])
|
|
44
54
|
.map(({ logical_path, artifact_id, entry_kind }) => ({
|
|
45
|
-
|
|
55
|
+
// Intermediate directory entries may be absent from an archive.
|
|
56
|
+
name: logical_path.slice(directory.logical_path.length + 1),
|
|
46
57
|
artifact_id,
|
|
47
58
|
entry_kind,
|
|
48
59
|
}))
|
|
49
|
-
.sort((left, right) =>
|
|
60
|
+
.sort((left, right) => compareDirectoryChildNames(left.name, right.name));
|
|
50
61
|
const node = createArtifactNode({
|
|
51
62
|
sha256: digestCanonical({ kind: "directory", children }),
|
|
52
63
|
size: 0,
|
|
@@ -76,7 +87,9 @@ export const createRootNode = (input) => createArtifactNode({
|
|
|
76
87
|
kind: input.directory ||
|
|
77
88
|
["zip", "ipa", "apk", "msix", "appx", "asar", "dmg", "pkg"].includes(input.format)
|
|
78
89
|
? "container"
|
|
79
|
-
:
|
|
90
|
+
: input.format === "dos-mz"
|
|
91
|
+
? "executable"
|
|
92
|
+
: classifyArtifactPath(input.path).kind,
|
|
80
93
|
format: input.format,
|
|
81
94
|
executable: false,
|
|
82
95
|
contentState: "materialized",
|
|
@@ -156,12 +169,14 @@ export const createArtifactEdges = (rootArtifactId, occurrences, producer) => {
|
|
|
156
169
|
}
|
|
157
170
|
return edges;
|
|
158
171
|
};
|
|
159
|
-
export const nearestParent = (path, occurrences) => {
|
|
172
|
+
export const nearestParent = (path, occurrences, expandedContainerIds) => {
|
|
160
173
|
const parts = path.split("/");
|
|
161
174
|
while (parts.length > 1) {
|
|
162
175
|
parts.pop();
|
|
163
176
|
const candidate = occurrences.get(parts.join("/"));
|
|
164
|
-
if (candidate
|
|
177
|
+
if (candidate !== undefined &&
|
|
178
|
+
(candidate.entry_kind === "directory" ||
|
|
179
|
+
expandedContainerIds.has(candidate.occurrence_id)))
|
|
165
180
|
return candidate;
|
|
166
181
|
}
|
|
167
182
|
return undefined;
|
|
@@ -191,7 +206,7 @@ export const classifyArtifactPath = (path) => {
|
|
|
191
206
|
return { kind: "resource", format: "file" };
|
|
192
207
|
};
|
|
193
208
|
/** Classify executable formats from bytes while retaining path-specific roles. */
|
|
194
|
-
export const classifyArtifactContent = (path, prefix) => {
|
|
209
|
+
export const classifyArtifactContent = (path, prefix, fileSize = prefix.length) => {
|
|
195
210
|
const byPath = classifyArtifactPath(path);
|
|
196
211
|
if (prefix.length >= 4) {
|
|
197
212
|
const magic = prefix.readUInt32BE(0);
|
|
@@ -215,11 +230,29 @@ export const classifyArtifactContent = (path, prefix) => {
|
|
|
215
230
|
format: "elf",
|
|
216
231
|
};
|
|
217
232
|
}
|
|
218
|
-
if (prefix.length >= 2 && prefix[0] === 0x4d && prefix[1] === 0x5a)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
233
|
+
if (prefix.length >= 2 && prefix[0] === 0x4d && prefix[1] === 0x5a) {
|
|
234
|
+
if (!Number.isSafeInteger(fileSize) ||
|
|
235
|
+
fileSize < prefix.length ||
|
|
236
|
+
prefix.length < Math.min(fileSize, 64))
|
|
237
|
+
return { kind: "unknown", format: "unknown" };
|
|
238
|
+
const windowsOffset = mzWindowsHeaderOffset(prefix);
|
|
239
|
+
if (windowsOffset !== null) {
|
|
240
|
+
if (windowsOffset >= 64 &&
|
|
241
|
+
windowsOffset <= prefix.length - 4 &&
|
|
242
|
+
prefix
|
|
243
|
+
.subarray(windowsOffset, windowsOffset + 4)
|
|
244
|
+
.equals(Buffer.from([0x50, 0x45, 0, 0])))
|
|
245
|
+
return {
|
|
246
|
+
kind: byPath.kind === "native-addon" ? "native-addon" : "executable",
|
|
247
|
+
format: "pe",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
else if (parseDosMzHeader(prefix, fileSize).ok) {
|
|
251
|
+
return { kind: "executable", format: "dos-mz" };
|
|
252
|
+
}
|
|
253
|
+
// Missing bounded evidence and malformed MZ bytes both remain unclassified.
|
|
254
|
+
return { kind: "unknown", format: "unknown" };
|
|
255
|
+
}
|
|
223
256
|
return byPath;
|
|
224
257
|
};
|
|
225
258
|
export const digestCanonical = (value) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { open } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { classifyArtifactContent } from "../ArtifactGraphConstruction.js";
|
|
3
|
+
import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "./hash.js";
|
|
3
4
|
import { hasZipSignature, zipPackageFormatForPath, } from "../../domain/zipPackageFormat.js";
|
|
4
5
|
const classifyContainerExtension = (path) => {
|
|
5
6
|
const lower = path.toLowerCase();
|
|
@@ -19,24 +20,15 @@ export const classifyRoot = async (path, directory) => {
|
|
|
19
20
|
return extensionFormat;
|
|
20
21
|
const handle = await open(path, "r");
|
|
21
22
|
try {
|
|
22
|
-
const magic = Buffer.alloc(
|
|
23
|
+
const magic = Buffer.alloc(ARTIFACT_CLASSIFICATION_PREFIX_BYTES);
|
|
23
24
|
const observed = await handle.read(magic, 0, magic.length, 0);
|
|
24
|
-
|
|
25
|
+
const prefix = magic.subarray(0, observed.bytesRead);
|
|
26
|
+
if (hasZipSignature(prefix))
|
|
25
27
|
return "zip";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if ([0xcafebabe, 0xbebafeca, 0xcafebabf, 0xbfbafeca].includes(header))
|
|
29
|
-
return "mach-o-universal";
|
|
30
|
-
if ([0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(header))
|
|
31
|
-
return "mach-o";
|
|
32
|
-
if (magic.equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46])))
|
|
33
|
-
return "elf";
|
|
34
|
-
}
|
|
35
|
-
if (observed.bytesRead >= 2 && magic[0] === 0x4d && magic[1] === 0x5a)
|
|
36
|
-
return "pe";
|
|
28
|
+
return classifyArtifactContent(path, prefix, (await handle.stat()).size)
|
|
29
|
+
.format;
|
|
37
30
|
}
|
|
38
31
|
finally {
|
|
39
32
|
await handle.close();
|
|
40
33
|
}
|
|
41
|
-
return classifyArtifactPath(path).format;
|
|
42
34
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
|
3
3
|
import { streamChunkToBuffer } from "../../artifacts/StreamBytes.js";
|
|
4
|
+
/** Bounded classification evidence; this is not an executable format size limit. */
|
|
5
|
+
export const ARTIFACT_CLASSIFICATION_PREFIX_BYTES = 8_192;
|
|
4
6
|
export const abortIfNeeded = (signal) => {
|
|
5
7
|
if (signal?.aborted === true)
|
|
6
8
|
throw new ArtifactReaderFailure("cancelled", "Artifact inventory cancelled");
|
|
@@ -15,8 +17,8 @@ export const hashReadable = async (stream, signal) => {
|
|
|
15
17
|
const chunk = streamChunkToBuffer(raw);
|
|
16
18
|
bytes += chunk.length;
|
|
17
19
|
hash.update(chunk);
|
|
18
|
-
if (prefixBytes <
|
|
19
|
-
const selected = chunk.subarray(0,
|
|
20
|
+
if (prefixBytes < ARTIFACT_CLASSIFICATION_PREFIX_BYTES) {
|
|
21
|
+
const selected = chunk.subarray(0, ARTIFACT_CLASSIFICATION_PREFIX_BYTES - prefixBytes);
|
|
20
22
|
prefixes.push(selected);
|
|
21
23
|
prefixBytes += selected.length;
|
|
22
24
|
}
|
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const resolveNativeMountPolicy = (approved, enabled) => {
|
|
4
|
-
if (!approved)
|
|
5
|
-
return { status: "disabled" };
|
|
6
|
-
if (!enabled)
|
|
7
|
-
throw new ArtifactReaderFailure("unavailable", "Native DMG mounting is disabled by operator policy");
|
|
8
|
-
return { status: "approved" };
|
|
9
|
-
};
|
|
10
|
-
/** Resolve parsed caller intent and operator policy before artifact scanning. */
|
|
11
|
-
export const resolveArtifactIntegrityPolicy = (intent, enabled) => {
|
|
12
|
-
if (intent.mode === "fail")
|
|
13
|
-
return intent;
|
|
14
|
-
if (!enabled)
|
|
15
|
-
throw new ArtifactReaderFailure("policy", "Integrity continuation requires explicit approval and operator policy");
|
|
16
|
-
return intent;
|
|
17
|
-
};
|
|
1
|
+
/** Preserve the explicit integrity admission choice without changing verification. */
|
|
2
|
+
export const resolveArtifactIntegrityPolicy = (intent) => intent;
|
|
@@ -3,7 +3,7 @@ import { DirectoryArtifactReader } from "../../artifacts/DirectoryArtifactReader
|
|
|
3
3
|
import { MachOSliceArtifactReader } from "../../artifacts/MachOSliceArtifactReader.js";
|
|
4
4
|
import { NativeDmgArtifactReader } from "../../artifacts/NativeDmgArtifactReader.js";
|
|
5
5
|
import { ZipArtifactReader } from "../../artifacts/ZipArtifactReader.js";
|
|
6
|
-
export const createReader = async (path, format,
|
|
6
|
+
export const createReader = async (path, format, signal) => {
|
|
7
7
|
switch (format) {
|
|
8
8
|
case "directory":
|
|
9
9
|
return new DirectoryArtifactReader(path);
|
|
@@ -20,7 +20,7 @@ export const createReader = async (path, format, nativeMount, signal) => {
|
|
|
20
20
|
? new MachOSliceArtifactReader(path)
|
|
21
21
|
: undefined;
|
|
22
22
|
case "dmg":
|
|
23
|
-
if (
|
|
23
|
+
if (process.platform !== "darwin")
|
|
24
24
|
return undefined;
|
|
25
25
|
return NativeDmgArtifactReader.create(path, signal);
|
|
26
26
|
default:
|
|
@@ -32,7 +32,7 @@ export const inventoryLimitations = (format, reader) => {
|
|
|
32
32
|
return [];
|
|
33
33
|
if (format === "dmg" || format === "pkg")
|
|
34
34
|
return [
|
|
35
|
-
`${format.toUpperCase()} root hash is observed; child inventory requires
|
|
35
|
+
`${format.toUpperCase()} root hash is observed; child inventory requires a native macOS adapter.`,
|
|
36
36
|
];
|
|
37
37
|
if (format === "mach-o-universal" && process.platform !== "darwin")
|
|
38
38
|
return ["Universal Mach-O slices require the native macOS lipo adapter."];
|
|
@@ -7,7 +7,7 @@ import { classifyRoot } from "./classify.js";
|
|
|
7
7
|
import { hashReadable } from "./hash.js";
|
|
8
8
|
import { createReader, inventoryLimitations } from "./reader.js";
|
|
9
9
|
import { scanReader, } from "./scanReader.js";
|
|
10
|
-
import {
|
|
10
|
+
import { STRICT_INTEGRITY_POLICY, } from "./types.js";
|
|
11
11
|
export const scanCanonicalArtifactInventory = async (path, options = {}) => {
|
|
12
12
|
const integrity = options.integrity ?? STRICT_INTEGRITY_POLICY;
|
|
13
13
|
const metadata = await lstat(path);
|
|
@@ -15,7 +15,7 @@ export const scanCanonicalArtifactInventory = async (path, options = {}) => {
|
|
|
15
15
|
const rootDigest = metadata.isDirectory()
|
|
16
16
|
? null
|
|
17
17
|
: await hashReadable(createReadStream(path), options.signal);
|
|
18
|
-
const reader = await createReader(path, rootFormat, options.
|
|
18
|
+
const reader = await createReader(path, rootFormat, options.signal);
|
|
19
19
|
try {
|
|
20
20
|
const { nodes, occurrences, pendingContradictions } = await scanReader(reader, options.signal, integrity);
|
|
21
21
|
return await buildInventorySnapshot({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
1
2
|
import { ArtifactPathRegistry, normalizeArtifactPath, } from "../../artifacts/ArtifactPaths.js";
|
|
2
3
|
import { ArtifactReaderFailure, } from "../../artifacts/ArtifactReader.js";
|
|
3
4
|
import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js";
|
|
@@ -19,8 +20,14 @@ export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_PO
|
|
|
19
20
|
pendingContradictions,
|
|
20
21
|
occurrenceByPath: new Map(),
|
|
21
22
|
registry: new ArtifactPathRegistry(),
|
|
23
|
+
expandedContainerIds: new Set(),
|
|
22
24
|
};
|
|
23
25
|
await visitArtifactEntries(context, reader, "");
|
|
26
|
+
// Archive directories may appear after their children. Resolve containment
|
|
27
|
+
// against the complete index before directory identities are materialized.
|
|
28
|
+
for (const occurrence of occurrences)
|
|
29
|
+
occurrence.parent_occurrence_id =
|
|
30
|
+
nearestParent(occurrence.logical_path, context.occurrenceByPath, context.expandedContainerIds)?.occurrence_id ?? null;
|
|
24
31
|
return { nodes, occurrences, pendingContradictions };
|
|
25
32
|
};
|
|
26
33
|
const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
@@ -50,8 +57,7 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
|
50
57
|
: `${frame.prefix}/${entry.path}`);
|
|
51
58
|
const expandableAsar = isExpandableAsar(entry, logicalPath);
|
|
52
59
|
context.registry.add(logicalPath, expandableAsar ? "directory" : entry.kind);
|
|
53
|
-
const
|
|
54
|
-
const occurrence = createOccurrence(entry, logicalPath, parent?.occurrence_id ?? null);
|
|
60
|
+
const occurrence = createOccurrence(entry, logicalPath, null);
|
|
55
61
|
let digested;
|
|
56
62
|
try {
|
|
57
63
|
digested = await digestArtifactEntry(context, frame.reader, entry, logicalPath);
|
|
@@ -75,6 +81,8 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
|
75
81
|
context.occurrenceByPath.set(logicalPath, occurrence);
|
|
76
82
|
if (expandableAsar && digested?.mismatched !== true) {
|
|
77
83
|
const nested = new AsarArtifactReader(entry.adapterKey);
|
|
84
|
+
// Only traversed containers can own members, not opaque ASAR-named files.
|
|
85
|
+
context.expandedContainerIds.add(occurrence.occurrence_id);
|
|
78
86
|
stack.push({
|
|
79
87
|
reader: nested,
|
|
80
88
|
prefix: logicalPath,
|
|
@@ -116,7 +124,7 @@ const digestArtifactEntry = async (context, currentReader, entry, logicalPath) =
|
|
|
116
124
|
}
|
|
117
125
|
const classified = entry.kind === "slice"
|
|
118
126
|
? { kind: "universal-slice", format: "mach-o" }
|
|
119
|
-
: classifyArtifactContent(logicalPath, digest.prefix);
|
|
127
|
+
: classifyArtifactContent(logicalPath, digest.prefix, digest.bytes);
|
|
120
128
|
return {
|
|
121
129
|
node: createArtifactNode({
|
|
122
130
|
sha256: digest.sha256,
|
|
@@ -136,7 +144,7 @@ const digestArtifactEntry = async (context, currentReader, entry, logicalPath) =
|
|
|
136
144
|
};
|
|
137
145
|
const isExpandableAsar = (entry, logicalPath) => entry.kind === "file" &&
|
|
138
146
|
logicalPath.toLowerCase().endsWith(".asar") &&
|
|
139
|
-
entry.adapterKey
|
|
147
|
+
isAbsolute(entry.adapterKey);
|
|
140
148
|
const isUnavailableUnpackedEntry = (cause, entry) => entry.unpacked &&
|
|
141
149
|
cause instanceof ArtifactReaderFailure &&
|
|
142
150
|
cause.reason === "unavailable";
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { analysisProfilesEqual, } from "../domain/analysisProfile.js";
|
|
3
|
-
import { AnalysisCancelledError,
|
|
3
|
+
import { AnalysisCancelledError, } from "../domain/errors.js";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
5
6
|
import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
|
|
6
7
|
import { SessionProviderRouter, } from "./SessionProviderRouter.js";
|
|
7
8
|
import { BinarySessionRecords } from "./BinarySessionRecords.js";
|
|
8
9
|
import { binarySessionStatus } from "./BinarySessionStatus.js";
|
|
9
10
|
import { resolveSessionOpen, } from "./BinarySessionOpen.js";
|
|
10
|
-
import { prepareSessionExecution } from "./BinarySessionExecution.js";
|
|
11
|
+
import { bindExecutionTarget, commitExecutionProfile, prepareSessionExecution, } from "./BinarySessionExecution.js";
|
|
11
12
|
import { closeAnalysisClient } from "./AnalysisClientCleanup.js";
|
|
12
13
|
const OFFICIAL_OPERATIONS = new Set(GENERATED_MCP_TOOL_CATALOG.filter(({ kind }) => kind === "official-proxy").map(({ name }) => name));
|
|
13
14
|
const ENHANCED_OPERATIONS = new Set(GENERATED_MCP_TOOL_CATALOG.filter(({ kind }) => kind === "enhanced").map(({ name }) => name));
|
|
@@ -143,10 +144,12 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
143
144
|
runId,
|
|
144
145
|
};
|
|
145
146
|
this.#clearRuntimeAvailability();
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
if (options.snapshot === undefined) {
|
|
148
|
+
if (profile === null)
|
|
149
|
+
this.clearSnapshot();
|
|
150
|
+
else
|
|
151
|
+
this.selectSnapshot(target, profile);
|
|
152
|
+
}
|
|
150
153
|
if (options.snapshot !== undefined) {
|
|
151
154
|
const imported = this.importAnalysisSnapshot(options.snapshot);
|
|
152
155
|
if (!imported.ok) {
|
|
@@ -216,7 +219,9 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
216
219
|
operation: name,
|
|
217
220
|
parameters: arguments_,
|
|
218
221
|
unboundOperationError: (operation, route) => this.#providerRouter.unboundOperationError(operation, route),
|
|
219
|
-
lookupSnapshot: (target, profile, operation, parameters) => operation === "decode_interface_builder"
|
|
222
|
+
lookupSnapshot: (target, profile, operation, parameters) => operation === "decode_interface_builder" ||
|
|
223
|
+
operation === "inspect_asset_catalog" ||
|
|
224
|
+
operation === "inspect_keyed_archive"
|
|
220
225
|
? undefined
|
|
221
226
|
: this.lookupSnapshot(target, profile, operation, parameters),
|
|
222
227
|
});
|
|
@@ -234,7 +239,21 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
234
239
|
if (profiled.ok &&
|
|
235
240
|
cacheable &&
|
|
236
241
|
profile !== undefined &&
|
|
237
|
-
name !== "decode_interface_builder"
|
|
242
|
+
name !== "decode_interface_builder" &&
|
|
243
|
+
name !== "inspect_asset_catalog" &&
|
|
244
|
+
name !== "inspect_keyed_archive") {
|
|
245
|
+
const evidence = createEvidence(profiled.value.subject ?? active.target, profiled.value.provider, {
|
|
246
|
+
operation: name,
|
|
247
|
+
parameters: arguments_,
|
|
248
|
+
result: profiled.value.result,
|
|
249
|
+
analysisProfile: profile,
|
|
250
|
+
rawResult: profiled.value.rawResult,
|
|
251
|
+
limitations: profiled.value.limitations,
|
|
252
|
+
locations: profiled.value.locations,
|
|
253
|
+
});
|
|
254
|
+
const recorded = this.recordEvidence(evidence);
|
|
255
|
+
if (!recorded.ok)
|
|
256
|
+
return recorded;
|
|
238
257
|
this.recordSnapshot({
|
|
239
258
|
target: active.target,
|
|
240
259
|
profile,
|
|
@@ -242,6 +261,7 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
242
261
|
parameters: arguments_,
|
|
243
262
|
execution: profiled.value,
|
|
244
263
|
});
|
|
264
|
+
}
|
|
245
265
|
else if (profiled.ok && capability?.effects.mutatesArtifact === true) {
|
|
246
266
|
this.invalidateSnapshot();
|
|
247
267
|
}
|
|
@@ -363,38 +383,3 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
363
383
|
}
|
|
364
384
|
}
|
|
365
385
|
const isAborted = (signal) => signal?.aborted === true;
|
|
366
|
-
const commitExecutionProfile = (operation, result, profile) => {
|
|
367
|
-
if (!result.ok || profile === undefined)
|
|
368
|
-
return result;
|
|
369
|
-
const provider = result.value.provider;
|
|
370
|
-
if (provider.id !== profile.provider.id ||
|
|
371
|
-
provider.name !== profile.provider.name ||
|
|
372
|
-
provider.version !== profile.provider.version)
|
|
373
|
-
return err(new ProviderAdapterError(profile.provider.id, `${operation}:profile`));
|
|
374
|
-
return ok({
|
|
375
|
-
...result.value,
|
|
376
|
-
analysisProfile: structuredClone(profile),
|
|
377
|
-
});
|
|
378
|
-
};
|
|
379
|
-
const bindExecutionTarget = (result, operation, target) => {
|
|
380
|
-
if (!result.ok)
|
|
381
|
-
return result;
|
|
382
|
-
const subject = {
|
|
383
|
-
path: target.path,
|
|
384
|
-
sha256: target.sha256,
|
|
385
|
-
format: target.format === "analysis-database"
|
|
386
|
-
? "analysis-database"
|
|
387
|
-
: target.format,
|
|
388
|
-
...(target.architecture === undefined
|
|
389
|
-
? {}
|
|
390
|
-
: { architecture: target.architecture }),
|
|
391
|
-
};
|
|
392
|
-
if (result.value.subject !== null &&
|
|
393
|
-
result.value.subject.sha256 !== target.sha256) {
|
|
394
|
-
if (!isArtifactInventorySubject(operation, result.value.subject, target))
|
|
395
|
-
return err(new ProviderAdapterError(result.value.provider.id, `${operation}:subject`));
|
|
396
|
-
}
|
|
397
|
-
return ok({ ...result.value, subject: result.value.subject ?? subject });
|
|
398
|
-
};
|
|
399
|
-
const isArtifactInventorySubject = (operation, subject, target) => (operation === "inventory_artifact" || operation === "inspect_artifact") &&
|
|
400
|
-
subject.path === (target.sourcePath ?? target.path);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnalysisCapabilityUnavailableError, NoBinaryOpenError, } from "../domain/errors.js";
|
|
1
|
+
import { AnalysisCapabilityUnavailableError, NoBinaryOpenError, ProviderAdapterError, } from "../domain/errors.js";
|
|
2
2
|
import { err, ok } from "../domain/result.js";
|
|
3
3
|
import { isSnapshotCacheable } from "./AnalysisSnapshotCache.js";
|
|
4
4
|
/** Resolve capability, profile, and snapshot state before invoking a provider. */
|
|
@@ -26,3 +26,39 @@ export const prepareSessionExecution = (input) => {
|
|
|
26
26
|
: undefined;
|
|
27
27
|
return ok({ active, capability, profile, cacheable, cached });
|
|
28
28
|
};
|
|
29
|
+
/** Attach the selected profile only when the provider identity agrees. */
|
|
30
|
+
export const commitExecutionProfile = (operation, result, profile) => {
|
|
31
|
+
if (!result.ok || profile === undefined)
|
|
32
|
+
return result;
|
|
33
|
+
const provider = result.value.provider;
|
|
34
|
+
if (provider.id !== profile.provider.id ||
|
|
35
|
+
provider.name !== profile.provider.name ||
|
|
36
|
+
provider.version !== profile.provider.version)
|
|
37
|
+
return err(new ProviderAdapterError(profile.provider.id, `${operation}:profile`));
|
|
38
|
+
return ok({
|
|
39
|
+
...result.value,
|
|
40
|
+
analysisProfile: structuredClone(profile),
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
/** Bind an execution to the selected target, preserving valid artifact subjects. */
|
|
44
|
+
export const bindExecutionTarget = (result, operation, target) => {
|
|
45
|
+
if (!result.ok)
|
|
46
|
+
return result;
|
|
47
|
+
const subject = {
|
|
48
|
+
path: target.path,
|
|
49
|
+
sha256: target.sha256,
|
|
50
|
+
format: target.format === "analysis-database"
|
|
51
|
+
? "analysis-database"
|
|
52
|
+
: target.format,
|
|
53
|
+
...(target.architecture === undefined
|
|
54
|
+
? {}
|
|
55
|
+
: { architecture: target.architecture }),
|
|
56
|
+
};
|
|
57
|
+
if (result.value.subject !== null &&
|
|
58
|
+
result.value.subject.sha256 !== target.sha256 &&
|
|
59
|
+
!isArtifactInventorySubject(operation, result.value.subject, target))
|
|
60
|
+
return err(new ProviderAdapterError(result.value.provider.id, `${operation}:subject`));
|
|
61
|
+
return ok({ ...result.value, subject: result.value.subject ?? subject });
|
|
62
|
+
};
|
|
63
|
+
const isArtifactInventorySubject = (operation, subject, target) => (operation === "inventory_artifact" || operation === "inspect_artifact") &&
|
|
64
|
+
subject.path === (target.sourcePath ?? target.path);
|