rea-agents 5.0.0 → 6.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 +157 -650
- package/bridge/mitmproxy/capture.py +210 -0
- package/bridge/native/rea_lldb_tracer.py +303 -0
- package/bridge/process/ProcessRunTokenReader.swift +263 -0
- package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
- package/bridge/pwndbg/core_context.py +101 -0
- package/bridge/pwndbg/launch.py +39 -0
- package/bridge/pwndbg/launch_impl.py +34 -0
- package/bridge/pwntools/decoder_runtime.py +59 -0
- package/bridge/pwntools/layout.py +39 -0
- package/bridge/pwntools/layout_impl.py +309 -0
- package/bridge/pwntools/recorded_crash.py +39 -0
- package/bridge/pwntools/recorded_crash_impl.py +143 -0
- package/dist/android/JadxProvider.js +1 -0
- package/dist/application/CapabilityInventory.js +21 -0
- package/dist/application/DirectAnalysis.js +97 -23
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +132 -0
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/binary/AnalysisSnapshotCache.js +49 -6
- package/dist/application/binary/BinarySession.js +38 -10
- package/dist/application/binary/BinarySessionOpen.js +16 -3
- package/dist/application/binary/BinarySessionRecords.js +20 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +57 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +60 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +62 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +15 -2
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +42 -23
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +74 -24
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +23 -10
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +145 -70
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +5 -5
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +10 -10
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +4 -4
- package/dist/artifacts/ArtifactProvider.js +30 -3
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/MachoLoadCommandReader.js +294 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +3 -3
- package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
- package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
- package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +3 -3
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureEventHandlers.js +90 -2
- package/dist/browser/CdpCaptureEvents.js +9 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +12 -3
- package/dist/browser/history/CaptureFailures.js +101 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +12 -0
- package/dist/browser/history/HarCapture.js +165 -0
- package/dist/browser/history/HarCaptureAdapter.js +20 -0
- package/dist/browser/history/HarCaptureProcess.js +57 -0
- package/dist/browser/history/HarJson.js +91 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +186 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/artifactCommands.js +26 -1
- package/dist/cli/binaryDiagnosticsCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +8 -8
- package/dist/cli/electronCommands.js +16 -9
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +16 -3
- package/dist/cli/jsonOutput.js +133 -0
- package/dist/cli/nativeCallCommands.js +35 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/streamedJsonOutput.js +56 -0
- package/dist/cli/utilityCommands.js +2 -0
- package/dist/cli/webNetworkCaptureCommands.js +40 -0
- package/dist/cli.js +9 -3
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -0
- package/dist/cliJsonInput.js +30 -1
- package/dist/cliOutput.js +21 -6
- package/dist/composition/binaryDiagnostics.js +8 -0
- package/dist/composition/evm.js +4 -0
- package/dist/composition/webNetworkCaptures.js +6 -0
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/managed/managedToolContracts.js +7 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +17 -1
- package/dist/contracts/officialToolContracts.js +12 -9
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/sessionLifecycleInputs.js +22 -5
- package/dist/contracts/sessionStatusContract.js +10 -2
- package/dist/contracts/sessionToolContracts.js +8 -1
- package/dist/contracts/sessionToolSchemas.js +10 -3
- package/dist/contracts/toolContractExamples.js +1 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -1
- package/dist/contracts/toolOutputSchemaPrimitives.js +1 -1
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +15 -0
- package/dist/domain/analysisErrorCore.js +59 -5
- package/dist/domain/analysisErrorPresentation.js +29 -1
- package/dist/domain/analysisErrorProjection.js +52 -2
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +367 -0
- package/dist/domain/apple/dylibResolutionFindings.js +75 -0
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +9 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/changedBehavior.js +3 -3
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +17 -5
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +92 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +8 -1
- package/dist/domain/javascript/electronActiveObservation.js +9 -4
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptSemanticGraph.js +21 -5
- package/dist/domain/jsonValue.js +4 -0
- package/dist/domain/localPath.js +2 -0
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/nativeCallObservation.js +164 -0
- package/dist/domain/native/objcSwiftMetadata.js +0 -39
- package/dist/domain/native/recordedCrash.js +266 -0
- package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
- package/dist/domain/{processCapture.js → process/processCapture.js} +139 -2
- package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
- package/dist/domain/process/processCaptureParsing.js +54 -0
- package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
- package/dist/domain/{processComparison.js → process/processComparison.js} +1 -1
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +3 -3
- package/dist/domain/reconstructionVerificationSchemas.js +1 -1
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +3 -3
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
- package/dist/dotnet/ManagedMemberInspector.js +4 -2
- package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
- package/dist/dotnet/ManagedMemberRows.js +14 -3
- package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
- package/dist/dotnet/ManagedMetadataInventory.js +38 -28
- package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
- package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
- package/dist/dotnet/ManagedPeReader.js +11 -0
- package/dist/evm/EvmBytecodeCarrier.js +21 -0
- package/dist/evm/EvmWorkerLimits.js +40 -0
- package/dist/evm/EvmoleFailures.js +126 -0
- package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
- package/dist/evm/EvmoleInterfaceProvider.js +273 -0
- package/dist/evm/EvmoleInterfaceWorker.js +87 -0
- package/dist/evm/EvmoleRelease.js +16 -0
- package/dist/firmware/FirmwareCommand.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraLauncher.js +1 -0
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +1 -1
- package/dist/hopper/BridgeLauncher.js +2 -0
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +1 -0
- package/dist/native/CommandRunner.js +2 -1
- package/dist/native/LldbCallTracer.js +278 -0
- package/dist/native/NativeCallObservation.js +135 -0
- package/dist/native/NativeMacOSProvider.js +19 -3
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/pwndbg/PwndbgCoreContext.js +160 -0
- package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
- package/dist/native/pwntools/PwntoolsFailures.js +180 -0
- package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
- package/dist/native/pwntools/PwntoolsRelease.js +19 -0
- package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +101 -0
- package/dist/process/DarwinProcessRunTokenReader.js +294 -0
- package/dist/process/OwnedCommand.js +113 -0
- package/dist/process/ProcessOwnership.js +263 -33
- package/dist/process/ProcessOwnershipObservation.js +161 -24
- package/dist/process/ProviderProcess.js +30 -3
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +17 -1
- package/dist/process/capture/ProcessCaptureLifecycle.js +615 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/createServer.js +22 -0
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerBinaryDiagnosticsTools.js +17 -0
- package/dist/server/registerEvidenceTools.js +1 -1
- package/dist/server/registerEvmTools.js +17 -0
- package/dist/server/registerProcessComparisonTool.js +1 -1
- package/dist/server/registerRecordedCrashTools.js +17 -0
- package/dist/server/registerSessionTools.js +2 -2
- package/dist/server/registerWebNetworkCaptureTool.js +28 -0
- package/dist/server/sessionAvailabilityPolicy.js +3 -0
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolResult.js +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +37 -9
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +23 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
- package/third_party/README.md +60 -0
- package/third_party/evmole/LICENSE +21 -0
- package/third_party/evmole/README.md +22 -0
- package/third_party/pwndbg/LICENSE.md +21 -0
- package/third_party/pwndbg/README.md +23 -0
- package/third_party/pwntools/README.md +40 -0
- package/dist/application/AuthorizedArtifactInventory.js +0 -7
- package/dist/application/ProcessCaptureLifecycle.js +0 -299
- package/dist/application/StoreFileLock.js +0 -124
- package/dist/contracts/processCaptureExample.js +0 -2
- package/dist/domain/bytecodeProvider.js +0 -178
- package/dist/domain/customProtocolCapture.js +0 -137
- package/dist/domain/eventProcessTree.js +0 -225
- package/dist/domain/mobileApplicationInvestigation.js +0 -159
- package/dist/domain/packageAnalysis.js +0 -123
- package/dist/domain/peInspection.js +0 -197
- package/dist/domain/processCaptureParsing.js +0 -21
- package/dist/domain/protocolCapture.js +0 -217
- package/dist/domain/runtimeIdentification.js +0 -212
- package/dist/generatedMcpToolCatalog.js +0 -37
- /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
- /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
- /package/dist/domain/{processScenario.js → process/processScenario.js} +0 -0
- /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
- /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
- /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
- /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
- /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
- /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
- /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
- /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
- /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { jsonValueSchema } from "./jsonValue.js";
|
|
1
2
|
import { analysisErrorCategory, analysisErrorRemediationAction, analysisErrorUserMessage, assertKnownAnalysisErrorTag, } from "./analysisErrorPresentation.js";
|
|
2
|
-
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisOutputError, AnalysisTimeoutError, } from "./analysisErrorCore.js";
|
|
3
|
+
import { AnalysisAccessDeniedError, AnalysisArtifactChangedError, AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisUnsupportedTargetError, AnalysisInputError, AnalysisOutputError, AnalysisTimeoutError, AnalysisResourceConstraintError, } from "./analysisErrorCore.js";
|
|
3
4
|
import { ArtifactOperationError } from "./artifactOperationError.js";
|
|
4
5
|
import { BinaryTargetError } from "./configurationErrors.js";
|
|
5
6
|
import { BrowserObservationError } from "./browserObservationError.js";
|
|
@@ -13,7 +14,10 @@ import {} from "./analysisErrorBase.js";
|
|
|
13
14
|
export const projectAnalysisError = (error) => {
|
|
14
15
|
assertKnownAnalysisErrorTag(error._tag);
|
|
15
16
|
const code = errorCode(error);
|
|
16
|
-
const
|
|
17
|
+
const primaryDetails = errorDetails(error);
|
|
18
|
+
const details = error.capturedOutput === undefined
|
|
19
|
+
? primaryDetails
|
|
20
|
+
: { ...primaryDetails, captured_output: { ...error.capturedOutput } };
|
|
17
21
|
return {
|
|
18
22
|
code,
|
|
19
23
|
category: analysisErrorCategory(error),
|
|
@@ -88,10 +92,14 @@ const STATIC_ERROR_CODES = {
|
|
|
88
92
|
AnalysisOutputError: "unreadable_output",
|
|
89
93
|
HopperProtocolError: "unreadable_output",
|
|
90
94
|
AnalysisInputError: "invalid_request",
|
|
95
|
+
AnalysisAccessDeniedError: "access_denied",
|
|
96
|
+
AnalysisArtifactChangedError: "artifact_changed",
|
|
91
97
|
AnalysisCapabilityUnavailableError: "capability_unavailable",
|
|
98
|
+
AnalysisUnsupportedTargetError: "unsupported_target",
|
|
92
99
|
AnalysisCancelledError: "cancelled",
|
|
93
100
|
HopperCancelledError: "cancelled",
|
|
94
101
|
AnalysisTimeoutError: "provider_timeout",
|
|
102
|
+
AnalysisResourceConstraintError: "resource_constraint",
|
|
95
103
|
HopperTimeoutError: "provider_timeout",
|
|
96
104
|
HopperProcessError: "provider_unavailable",
|
|
97
105
|
HopperStartError: "provider_unavailable",
|
|
@@ -120,6 +128,33 @@ const errorDetails = (error) => requestErrorDetails(error) ??
|
|
|
120
128
|
providerErrorDetails(error) ??
|
|
121
129
|
lifecycleErrorDetails(error);
|
|
122
130
|
const requestErrorDetails = (error) => {
|
|
131
|
+
if (error instanceof AnalysisUnsupportedTargetError)
|
|
132
|
+
return {
|
|
133
|
+
operation: error.operation,
|
|
134
|
+
path: error.path,
|
|
135
|
+
reason: error.reason,
|
|
136
|
+
};
|
|
137
|
+
if (error instanceof AnalysisResourceConstraintError)
|
|
138
|
+
return {
|
|
139
|
+
operation: error.operation,
|
|
140
|
+
resource: error.resource,
|
|
141
|
+
reason: error.reason,
|
|
142
|
+
reported_limits: error.reportedLimits,
|
|
143
|
+
};
|
|
144
|
+
if (error instanceof AnalysisArtifactChangedError)
|
|
145
|
+
return {
|
|
146
|
+
operation: error.operation,
|
|
147
|
+
path: error.path,
|
|
148
|
+
reason: error.reason,
|
|
149
|
+
boundary: "stable-artifact-read",
|
|
150
|
+
};
|
|
151
|
+
if (error instanceof AnalysisAccessDeniedError)
|
|
152
|
+
return {
|
|
153
|
+
operation: error.operation,
|
|
154
|
+
path: error.path,
|
|
155
|
+
system_code: error.systemCode,
|
|
156
|
+
boundary: "filesystem-read",
|
|
157
|
+
};
|
|
123
158
|
if (error instanceof AnalysisOutputError)
|
|
124
159
|
return { operation: error.operation, reason: error.reason };
|
|
125
160
|
if (error instanceof AnalysisInputError && error.issues.length > 0)
|
|
@@ -272,10 +307,24 @@ const lifecycleErrorDetails = (error) => {
|
|
|
272
307
|
return {
|
|
273
308
|
cleanup: "incomplete",
|
|
274
309
|
resources: [...error.cleanupResources],
|
|
310
|
+
...(error.cleanupReport === undefined
|
|
311
|
+
? {}
|
|
312
|
+
: { cleanup_report: jsonValueSchema.parse(error.cleanupReport) }),
|
|
313
|
+
...(error.executionFailure === undefined
|
|
314
|
+
? {}
|
|
315
|
+
: { execution_failure: error.executionFailure }),
|
|
316
|
+
...(error.partialObservation === undefined
|
|
317
|
+
? {}
|
|
318
|
+
: {
|
|
319
|
+
partial_observation: jsonValueSchema.parse(error.partialObservation),
|
|
320
|
+
}),
|
|
275
321
|
};
|
|
276
322
|
if (error._tag === "ProcessCaptureError" &&
|
|
277
323
|
error.userCategory === "cancelled")
|
|
278
324
|
return { operation: "process_capture", cleanup: "complete" };
|
|
325
|
+
if (error._tag === "ProcessCaptureError" &&
|
|
326
|
+
error.executionFailure !== undefined)
|
|
327
|
+
return { execution_failure: error.executionFailure };
|
|
279
328
|
if (error instanceof BinaryTargetError)
|
|
280
329
|
return {
|
|
281
330
|
path: error.path,
|
|
@@ -287,6 +336,7 @@ const lifecycleErrorDetails = (error) => {
|
|
|
287
336
|
return undefined;
|
|
288
337
|
};
|
|
289
338
|
const RETRYABLE_CODES = new Set([
|
|
339
|
+
"artifact_changed",
|
|
290
340
|
"invalid_request",
|
|
291
341
|
"provider_timeout",
|
|
292
342
|
"cancelled",
|
|
@@ -77,11 +77,26 @@ const entrySchema = z.object({
|
|
|
77
77
|
subject: subjectSchema.nullable(),
|
|
78
78
|
}),
|
|
79
79
|
});
|
|
80
|
+
const workflowEntrySchema = z.object({
|
|
81
|
+
query_id: prefixedDigestSchema("query"),
|
|
82
|
+
operation: z.string().min(1),
|
|
83
|
+
parameters: jsonObjectSchema,
|
|
84
|
+
execution: z.object({
|
|
85
|
+
result: jsonValueSchema,
|
|
86
|
+
raw_result: jsonValueSchema.nullable(),
|
|
87
|
+
provider: committedProviderSchema,
|
|
88
|
+
analysis_profile: analysisProfileSchema,
|
|
89
|
+
limitations: z.array(z.string()),
|
|
90
|
+
locations: z.array(evidenceLocationSchema),
|
|
91
|
+
subject: subjectSchema.nullable(),
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
80
94
|
/** Provider- and profile-exact cache of successful immutable analysis calls. */
|
|
81
95
|
export const analysisSnapshotSchema = z.object({
|
|
82
96
|
target: targetSchema,
|
|
83
97
|
binding: bindingSchema,
|
|
84
98
|
entries: z.array(entrySchema),
|
|
99
|
+
workflow_entries: z.array(workflowEntrySchema).optional(),
|
|
85
100
|
evidence_bundle: evidenceBundleSchema,
|
|
86
101
|
});
|
|
87
102
|
const canonicalJson = (value) => {
|
|
@@ -122,6 +137,11 @@ export const snapshotEvidenceForQuery = (snapshot, query) => {
|
|
|
122
137
|
if (!snapshotMatchesBinding(snapshot, target, bindingProfile))
|
|
123
138
|
return undefined;
|
|
124
139
|
const encodedParameters = canonicalJson(parameters);
|
|
140
|
+
const queryId = analysisQueryId(snapshot.target, snapshot.binding, operation, parameters);
|
|
141
|
+
const entry = snapshot.entries.find((candidate) => candidate.query_id === queryId);
|
|
142
|
+
const workflowEntry = snapshot.workflow_entries?.find((candidate) => candidate.query_id === queryId);
|
|
143
|
+
if (entry === undefined && workflowEntry === undefined)
|
|
144
|
+
return undefined;
|
|
125
145
|
return snapshot.evidence_bundle.records.find((record) => record.subject?.digest.sha256 === target.sha256 &&
|
|
126
146
|
record.operation === operation &&
|
|
127
147
|
record.provider.id === provider.id &&
|
|
@@ -129,8 +149,54 @@ export const snapshotEvidenceForQuery = (snapshot, query) => {
|
|
|
129
149
|
record.provider.version === provider.version &&
|
|
130
150
|
"analysis_profile" in record &&
|
|
131
151
|
analysisProfilesEqual(record.analysis_profile, evidenceProfile) &&
|
|
132
|
-
canonicalJson(record.parameters) === encodedParameters
|
|
152
|
+
canonicalJson(record.parameters) === encodedParameters &&
|
|
153
|
+
((entry !== undefined && evidenceMatchesEntry(record, entry, snapshot)) ||
|
|
154
|
+
(workflowEntry !== undefined &&
|
|
155
|
+
evidenceMatchesWorkflowEntry(record, workflowEntry, snapshot))));
|
|
156
|
+
};
|
|
157
|
+
/** Create one exact replay record for a derived application workflow result. */
|
|
158
|
+
export const createAnalysisSnapshotWorkflowEntry = (input) => {
|
|
159
|
+
const { target, binding, operation, parameters, execution } = input;
|
|
160
|
+
if (execution.provider.id !== execution.analysisProfile.provider.id ||
|
|
161
|
+
execution.provider.name !== execution.analysisProfile.provider.name ||
|
|
162
|
+
execution.provider.version !== execution.analysisProfile.provider.version)
|
|
163
|
+
throw new TypeError("Workflow snapshot execution provider does not match its profile");
|
|
164
|
+
return {
|
|
165
|
+
query_id: analysisQueryId(target, binding, operation, parameters),
|
|
166
|
+
operation,
|
|
167
|
+
parameters: jsonObjectSchema.parse(parameters),
|
|
168
|
+
execution: {
|
|
169
|
+
result: execution.result,
|
|
170
|
+
raw_result: execution.rawResult,
|
|
171
|
+
provider: execution.analysisProfile.provider,
|
|
172
|
+
analysis_profile: execution.analysisProfile,
|
|
173
|
+
limitations: [...execution.limitations],
|
|
174
|
+
locations: [...execution.locations],
|
|
175
|
+
subject: execution.subject === null
|
|
176
|
+
? null
|
|
177
|
+
: {
|
|
178
|
+
...execution.subject,
|
|
179
|
+
architecture: execution.subject.architecture ?? null,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
133
183
|
};
|
|
184
|
+
const evidenceMatchesEntry = (evidence, entry, snapshot) => isCorrespondingEvidence(evidence, snapshot) &&
|
|
185
|
+
canonicalJson({
|
|
186
|
+
query: evidenceQueryKey(evidence),
|
|
187
|
+
normalized_result: evidence.normalized_result,
|
|
188
|
+
raw_result: evidence.raw_result,
|
|
189
|
+
limitations: evidence.limitations,
|
|
190
|
+
locations: evidence.locations,
|
|
191
|
+
subject: evidence.subject === null
|
|
192
|
+
? null
|
|
193
|
+
: {
|
|
194
|
+
local_path: evidence.subject.local_path,
|
|
195
|
+
sha256: evidence.subject.digest.sha256,
|
|
196
|
+
format: evidence.subject.format,
|
|
197
|
+
architecture: evidence.subject.architecture,
|
|
198
|
+
},
|
|
199
|
+
}) === entryEvidenceKey(entry, snapshot.binding);
|
|
134
200
|
/** Compute the stable lookup key for one provider/profile-specific query. */
|
|
135
201
|
export const analysisQueryId = (target, binding, operation, parameters) => `query_${createHash("sha256")
|
|
136
202
|
.update(canonicalJson({ target, binding, operation, parameters }))
|
|
@@ -171,7 +237,9 @@ export const parseAnalysisSnapshot = (input) => {
|
|
|
171
237
|
throw new TypeError("Analysis snapshot evidence contains records for another target");
|
|
172
238
|
const ids = new Set();
|
|
173
239
|
const boundEntries = [];
|
|
240
|
+
const boundWorkflowEntries = [];
|
|
174
241
|
const index = createEvidenceIndex(parsed);
|
|
242
|
+
const workflowIndex = createWorkflowEvidenceIndex(parsed);
|
|
175
243
|
for (const entry of parsed.entries) {
|
|
176
244
|
if (entry.execution.provider.id !== parsed.binding.provider.id ||
|
|
177
245
|
entry.execution.provider.name !== parsed.binding.provider.name ||
|
|
@@ -192,10 +260,41 @@ export const parseAnalysisSnapshot = (input) => {
|
|
|
192
260
|
}
|
|
193
261
|
boundEntries.push(entry);
|
|
194
262
|
}
|
|
263
|
+
for (const entry of parsed.workflow_entries ?? []) {
|
|
264
|
+
if (entry.execution.provider.id !==
|
|
265
|
+
entry.execution.analysis_profile.provider.id ||
|
|
266
|
+
entry.execution.provider.name !==
|
|
267
|
+
entry.execution.analysis_profile.provider.name ||
|
|
268
|
+
entry.execution.provider.version !==
|
|
269
|
+
entry.execution.analysis_profile.provider.version)
|
|
270
|
+
throw new TypeError("Analysis snapshot workflow entry provider does not match its profile");
|
|
271
|
+
const expected = analysisQueryId(parsed.target, parsed.binding, entry.operation, entry.parameters);
|
|
272
|
+
if (entry.query_id !== expected)
|
|
273
|
+
throw new TypeError("Analysis snapshot workflow query identifier does not match");
|
|
274
|
+
if (ids.has(entry.query_id))
|
|
275
|
+
throw new TypeError("Analysis snapshot contains duplicate queries");
|
|
276
|
+
ids.add(entry.query_id);
|
|
277
|
+
if (!workflowEntryHasMatchingEvidence(entry, workflowIndex)) {
|
|
278
|
+
if (workflowEntryHasCorrespondingEvidence(entry, workflowIndex))
|
|
279
|
+
throw new TypeError(`Analysis snapshot workflow entry ${entry.operation} differs from its Evidence record`);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
boundWorkflowEntries.push(entry);
|
|
283
|
+
}
|
|
195
284
|
const sorted = [...parsed.entries].sort((left, right) => left.query_id.localeCompare(right.query_id));
|
|
196
285
|
if (JSON.stringify(parsed.entries) !== JSON.stringify(sorted))
|
|
197
286
|
throw new TypeError("Analysis snapshot entries are not canonical");
|
|
198
|
-
|
|
287
|
+
const sortedWorkflows = [...(parsed.workflow_entries ?? [])].sort((left, right) => left.query_id.localeCompare(right.query_id));
|
|
288
|
+
if (parsed.workflow_entries !== undefined &&
|
|
289
|
+
JSON.stringify(parsed.workflow_entries) !== JSON.stringify(sortedWorkflows))
|
|
290
|
+
throw new TypeError("Analysis snapshot workflow entries are not canonical");
|
|
291
|
+
return {
|
|
292
|
+
...parsed,
|
|
293
|
+
entries: boundEntries,
|
|
294
|
+
...(parsed.workflow_entries === undefined
|
|
295
|
+
? {}
|
|
296
|
+
: { workflow_entries: boundWorkflowEntries }),
|
|
297
|
+
};
|
|
199
298
|
};
|
|
200
299
|
const createEvidenceIndex = (snapshot) => {
|
|
201
300
|
const matching = new Set();
|
|
@@ -259,5 +358,70 @@ const entryEvidenceKey = (entry, binding) => canonicalJson({
|
|
|
259
358
|
architecture: entry.execution.subject.architecture,
|
|
260
359
|
},
|
|
261
360
|
});
|
|
361
|
+
const workflowEntryQueryKey = (entry) => canonicalJson({
|
|
362
|
+
operation: entry.operation,
|
|
363
|
+
parameters: entry.parameters,
|
|
364
|
+
provider: entry.execution.provider,
|
|
365
|
+
analysis_profile: entry.execution.analysis_profile,
|
|
366
|
+
});
|
|
367
|
+
const workflowEntryEvidenceKey = (entry) => canonicalJson({
|
|
368
|
+
query: workflowEntryQueryKey(entry),
|
|
369
|
+
normalized_result: entry.execution.result,
|
|
370
|
+
raw_result: entry.execution.raw_result,
|
|
371
|
+
limitations: entry.execution.limitations,
|
|
372
|
+
locations: entry.execution.locations,
|
|
373
|
+
subject: entry.execution.subject === null
|
|
374
|
+
? null
|
|
375
|
+
: {
|
|
376
|
+
local_path: entry.execution.subject.path,
|
|
377
|
+
sha256: entry.execution.subject.sha256,
|
|
378
|
+
format: entry.execution.subject.format,
|
|
379
|
+
architecture: entry.execution.subject.architecture,
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
const isWorkflowEvidence = (evidence, snapshot, entry) => evidence.predicate_type === "rea.analysis" &&
|
|
383
|
+
evidence.confidence === "derived" &&
|
|
384
|
+
evidence.authority === "shipped-artifact" &&
|
|
385
|
+
evidence.subject?.digest.sha256 === snapshot.target.sha256 &&
|
|
386
|
+
"analysis_profile" in evidence &&
|
|
387
|
+
analysisProfilesEqual(evidence.analysis_profile, entry.execution.analysis_profile) &&
|
|
388
|
+
evidence.provider.id === entry.execution.provider.id &&
|
|
389
|
+
evidence.provider.name === entry.execution.provider.name &&
|
|
390
|
+
evidence.provider.version === entry.execution.provider.version;
|
|
391
|
+
const createWorkflowEvidenceIndex = (snapshot) => {
|
|
392
|
+
const matching = new Set();
|
|
393
|
+
const corresponding = new Set();
|
|
394
|
+
for (const evidence of snapshot.evidence_bundle.records) {
|
|
395
|
+
if (evidence.predicate_type !== "rea.analysis" ||
|
|
396
|
+
evidence.confidence !== "derived" ||
|
|
397
|
+
evidence.authority !== "shipped-artifact" ||
|
|
398
|
+
evidence.subject?.digest.sha256 !== snapshot.target.sha256 ||
|
|
399
|
+
!("analysis_profile" in evidence))
|
|
400
|
+
continue;
|
|
401
|
+
corresponding.add(evidenceQueryKey(evidence));
|
|
402
|
+
matching.add(canonicalJson(evidenceContentProjection(evidence)));
|
|
403
|
+
}
|
|
404
|
+
return { matching, corresponding };
|
|
405
|
+
};
|
|
406
|
+
const workflowEntryHasMatchingEvidence = (entry, index) => index.matching.has(workflowEntryEvidenceKey(entry));
|
|
407
|
+
const workflowEntryHasCorrespondingEvidence = (entry, index) => index.corresponding.has(workflowEntryQueryKey(entry));
|
|
408
|
+
const evidenceMatchesWorkflowEntry = (evidence, entry, snapshot) => isWorkflowEvidence(evidence, snapshot, entry) &&
|
|
409
|
+
canonicalJson(evidenceContentProjection(evidence)) ===
|
|
410
|
+
workflowEntryEvidenceKey(entry);
|
|
411
|
+
const evidenceContentProjection = (evidence) => ({
|
|
412
|
+
query: evidenceQueryKey(evidence),
|
|
413
|
+
normalized_result: evidence.normalized_result,
|
|
414
|
+
raw_result: evidence.raw_result,
|
|
415
|
+
limitations: evidence.limitations,
|
|
416
|
+
locations: evidence.locations,
|
|
417
|
+
subject: evidence.subject === null
|
|
418
|
+
? null
|
|
419
|
+
: {
|
|
420
|
+
local_path: evidence.subject.local_path,
|
|
421
|
+
sha256: evidence.subject.digest.sha256,
|
|
422
|
+
format: evidence.subject.format,
|
|
423
|
+
architecture: evidence.subject.architecture,
|
|
424
|
+
},
|
|
425
|
+
});
|
|
262
426
|
/** Serialize a validated snapshot with byte-stable canonical entry ordering. */
|
|
263
427
|
export const serializeAnalysisSnapshot = (snapshot) => `${canonicalJson(parseAnalysisSnapshot(snapshot))}\n`;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const MAX_SYMLINK_HOPS = 32;
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a root-relative path one segment at a time, as `open` would:
|
|
4
|
+
* symlinks are followed inside the root, `..` applies to the real parent,
|
|
5
|
+
* and any escape above the root or through an absolute link stops.
|
|
6
|
+
*/
|
|
7
|
+
export const resolveTreePath = async (view, input) => {
|
|
8
|
+
const pending = segmentsOf(input);
|
|
9
|
+
const resolved = [];
|
|
10
|
+
let last;
|
|
11
|
+
let hops = 0;
|
|
12
|
+
while (pending.length > 0) {
|
|
13
|
+
const segment = pending.shift() ?? "";
|
|
14
|
+
if (segment === "..") {
|
|
15
|
+
if (resolved.length === 0)
|
|
16
|
+
return { kind: "escapes" };
|
|
17
|
+
resolved.pop();
|
|
18
|
+
last = { kind: "directory" };
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const path = [...resolved, segment].join("/");
|
|
22
|
+
const entry = await view.entry(path);
|
|
23
|
+
if (entry === undefined)
|
|
24
|
+
return { kind: "absent" };
|
|
25
|
+
if (entry.kind === "symlink") {
|
|
26
|
+
hops += 1;
|
|
27
|
+
if (hops > MAX_SYMLINK_HOPS)
|
|
28
|
+
return { kind: "absent" };
|
|
29
|
+
if (entry.target.startsWith("/"))
|
|
30
|
+
return { kind: "escapes" };
|
|
31
|
+
pending.unshift(...segmentsOf(entry.target));
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (entry.kind === "file" && pending.length > 0)
|
|
35
|
+
return { kind: "absent" };
|
|
36
|
+
resolved.push(segment);
|
|
37
|
+
last = entry;
|
|
38
|
+
}
|
|
39
|
+
return last?.kind === "file"
|
|
40
|
+
? { kind: "file", path: resolved.join("/") }
|
|
41
|
+
: { kind: "not-file" };
|
|
42
|
+
};
|
|
43
|
+
const segmentsOf = (path) => path.split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
44
|
+
export const directoryOf = (path) => {
|
|
45
|
+
const index = path.lastIndexOf("/");
|
|
46
|
+
return index < 0 ? "" : path.slice(0, index);
|
|
47
|
+
};
|
|
48
|
+
export const joinPath = (directory, rest) => directory === "" ? rest : rest === "" ? directory : `${directory}/${rest}`;
|
|
49
|
+
/** Expand one dyld path prefix relative to its owning image. */
|
|
50
|
+
export const expandPrefix = (raw, context) => {
|
|
51
|
+
const variable = /^@(executable_path|loader_path)(?:\/(.*))?$/u.exec(raw);
|
|
52
|
+
if (variable !== null) {
|
|
53
|
+
const rest = variable[2] ?? "";
|
|
54
|
+
if (variable[1] === "loader_path")
|
|
55
|
+
return { scope: "target", path: joinPath(context.ownerDirectory, rest) };
|
|
56
|
+
return context.executable === null
|
|
57
|
+
? { scope: "undetermined", path: raw }
|
|
58
|
+
: {
|
|
59
|
+
scope: "target",
|
|
60
|
+
path: joinPath(directoryOf(context.executable), rest),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (raw.startsWith("/"))
|
|
64
|
+
return { scope: "outside", path: raw };
|
|
65
|
+
return { scope: "undetermined", path: raw };
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Slices a process may load, best first, following dyld's graded
|
|
69
|
+
* architectures: an x86_64h process also accepts generic x86_64.
|
|
70
|
+
*/
|
|
71
|
+
const COMPATIBLE_ARCHITECTURES = {
|
|
72
|
+
x86_64h: ["x86_64h", "x86_64"],
|
|
73
|
+
};
|
|
74
|
+
export const compatibleSlice = (slices, process) => {
|
|
75
|
+
for (const architecture of COMPATIBLE_ARCHITECTURES[process] ?? [process]) {
|
|
76
|
+
const slice = slices.find((item) => item.architecture === architecture);
|
|
77
|
+
if (slice !== undefined)
|
|
78
|
+
return slice;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
};
|