rea-agents 6.2.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -23
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/bridge/hopper_bridge.py +2 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +59 -21
- package/dist/android/JadxSession.js +51 -9
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +85 -19
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +98 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +75 -27
- package/dist/application/DirectAnalysis.js +14 -8
- package/dist/application/DirectAnalysisCleanup.js +1 -2
- package/dist/application/DirectAnalysisStatus.js +3 -6
- package/dist/application/Doctor.js +27 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +10 -4
- package/dist/application/JsonFiles.js +16 -15
- package/dist/application/JsonInputFile.js +252 -0
- package/dist/application/LinuxHopper.js +6 -13
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +16 -3
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +103 -0
- package/dist/application/Setup.js +69 -10
- package/dist/application/SetupClientConfiguration.js +134 -23
- package/dist/application/SetupHost.js +102 -22
- package/dist/application/SetupPlan.js +18 -17
- package/dist/application/SetupSkill.js +81 -13
- package/dist/application/SupportedClients.js +305 -37
- package/dist/application/Uninstall.js +172 -8
- package/dist/application/UpdateMaintenance.js +23 -23
- package/dist/application/Utf8JsonInput.js +71 -0
- package/dist/application/WebScriptExportService.js +130 -57
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/android/AndroidAnalysisService.js +1 -1
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +18 -1
- package/dist/application/binary/BinarySessionOpen.js +9 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +20 -3
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +23 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -36
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +74 -36
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +53 -42
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +293 -238
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +120 -28
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +10 -20
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +11 -5
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +206 -66
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +18 -23
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +5 -2
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +6 -4
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +29 -15
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeCallRoutes.js +2 -4
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +34 -31
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +218 -80
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +179 -87
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +76 -49
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +134 -92
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +116 -50
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +87 -25
- package/dist/artifacts/inventory/hashStableRootArtifact.js +70 -0
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +73 -30
- package/dist/artifacts/inventory/scanReader.js +43 -20
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +72 -28
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +9 -3
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +48 -23
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +63 -7
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +208 -43
- package/dist/browser/PlaywrightScenarioSession.js +130 -65
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +35 -9
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +12 -13
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +14 -10
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -13
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +12 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +68 -22
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +11 -2
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +7 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +14 -7
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactComparisonExample.js +5 -5
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +104 -13
- package/dist/contracts/javascript/electronToolContracts.js +16 -3
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +5 -4
- package/dist/contracts/sessionToolSchemas.js +9 -4
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +7 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -4
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +5 -2
- package/dist/domain/analysisView/analysisView.js +53 -5
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/android/androidPartialObservation.js +36 -0
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +3 -3
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +39 -11
- package/dist/domain/artifactGraph.js +6 -4
- package/dist/domain/artifactIdentity.js +37 -9
- package/dist/domain/artifactInspection.js +10 -50
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +16 -17
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +12 -6
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +14 -15
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +20 -21
- package/dist/domain/javascript/electronStaticAnalysisNative.js +73 -41
- package/dist/domain/javascript/electronStaticAnalysisValues.js +24 -4
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +6 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +18 -14
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +91 -28
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +72 -45
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +16 -8
- package/dist/domain/javascript/javascriptAstFingerprint.js +60 -33
- package/dist/domain/javascript/javascriptAstValues.js +54 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +12 -7
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +15 -17
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +379 -30
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +43 -42
- package/dist/domain/javascript/javascriptSemanticGraph.js +205 -52
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +21 -11
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +139 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +774 -136
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +98 -41
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +9 -7
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +72 -28
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +100 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +33 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +4 -5
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +34 -48
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +25 -2
- package/dist/domain/javascript/javascriptSemanticValues.js +169 -30
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +13 -12
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +69 -31
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +47 -6
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +94 -59
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +102 -11
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +67 -0
- package/dist/domain/process/processCaptureValidation.js +83 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +62 -10
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +32 -23
- package/dist/domain/referenceSourceImportParsing.js +40 -48
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +23 -3
- package/dist/domain/webCaptureDiff.js +170 -30
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +5 -4
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +65 -31
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +73 -0
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +90 -8
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +123 -58
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperCleanup.js +1 -1
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +10 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +7 -3
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +100 -20
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +104 -51
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +116 -22
- package/dist/process/capture/ProcessCaptureLifecycle.js +363 -86
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +202 -47
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/analysisAdmission.js +8 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +118 -47
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +6 -7
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/helpers.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerArtifactTools.js +2 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +36 -5
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedTools.js +7 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerOfficialTools.js +31 -25
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +58 -21
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +38 -7
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +31 -1
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { inflateSync } from "node:zlib";
|
|
1
|
+
import { constants as zlibConstants, crc32, inflateSync } from "node:zlib";
|
|
2
|
+
import { AnalysisResourceConstraintError, AnalysisUnsupportedTargetError, } from "../domain/analysisErrorCore.js";
|
|
2
3
|
import { decodeCanonicalBase64 } from "../domain/webScreenshot.js";
|
|
4
|
+
/** Conservative allowance for the simultaneously live PNG comparison buffers. */
|
|
5
|
+
const PNG_COMPARISON_WORKING_MEMORY_BYTES = 256 * 1024 * 1024;
|
|
6
|
+
const PNG_INFLATE_CHUNK_BYTES = zlibConstants.Z_DEFAULT_CHUNK;
|
|
3
7
|
/** Compare two validated screenshots using deterministic RGBA metrics. */
|
|
4
8
|
export const comparePngScreenshots = (input) => {
|
|
5
|
-
|
|
6
|
-
const
|
|
9
|
+
admitEncodedInputPair(input.before, input.after);
|
|
10
|
+
const beforePlan = parsePng(input.before, "before");
|
|
11
|
+
const afterPlan = parsePng(input.after, "after");
|
|
12
|
+
admitPngPair(beforePlan, afterPlan);
|
|
13
|
+
const before = decodePng(beforePlan);
|
|
14
|
+
const after = decodePng(afterPlan);
|
|
7
15
|
if (before.width !== after.width || before.height !== after.height)
|
|
8
16
|
return {
|
|
9
17
|
status: "dimension_mismatch",
|
|
@@ -57,7 +65,7 @@ export const comparePngScreenshots = (input) => {
|
|
|
57
65
|
changed_ratio: changedPixels / pixels,
|
|
58
66
|
};
|
|
59
67
|
};
|
|
60
|
-
const
|
|
68
|
+
const parsePng = (artifact, field) => {
|
|
61
69
|
const bytes = decodeCanonicalBase64(artifact.data_base64);
|
|
62
70
|
if (bytes === undefined || !bytes.subarray(0, 8).equals(PNG_SIGNATURE))
|
|
63
71
|
throw new TypeError("Invalid PNG signature");
|
|
@@ -65,68 +73,229 @@ const decodePng = (artifact) => {
|
|
|
65
73
|
let header;
|
|
66
74
|
const compressed = [];
|
|
67
75
|
let sawEnd = false;
|
|
76
|
+
let sawPalette = false;
|
|
77
|
+
let imageDataEnded = false;
|
|
78
|
+
let paletteEntries = 0;
|
|
68
79
|
let transparentColor;
|
|
80
|
+
let sawTransparency = false;
|
|
81
|
+
let unsupportedReason;
|
|
69
82
|
while (offset < bytes.length) {
|
|
70
83
|
if (offset + 12 > bytes.length)
|
|
71
84
|
throw new TypeError("Truncated PNG chunk");
|
|
72
85
|
const length = bytes.readUInt32BE(offset);
|
|
73
|
-
|
|
86
|
+
if (length > 0x7fffffff)
|
|
87
|
+
throw new TypeError("Invalid PNG chunk length");
|
|
88
|
+
const type = bytes.subarray(offset + 4, offset + 8).toString("latin1");
|
|
74
89
|
const dataStart = offset + 8;
|
|
75
90
|
const dataEnd = dataStart + length;
|
|
76
91
|
if (dataEnd + 4 > bytes.length)
|
|
77
92
|
throw new TypeError("Truncated PNG data");
|
|
78
93
|
const data = bytes.subarray(dataStart, dataEnd);
|
|
79
|
-
if (
|
|
94
|
+
if (crc32(bytes.subarray(offset + 4, dataEnd)) !== bytes.readUInt32BE(dataEnd))
|
|
95
|
+
throw new TypeError("Invalid PNG chunk checksum");
|
|
96
|
+
if (!/^[A-Za-z]{4}$/u.test(type) || type[2] !== type[2]?.toUpperCase())
|
|
97
|
+
throw new TypeError("Invalid PNG chunk type");
|
|
98
|
+
if (type !== "IDAT" && compressed.length > 0)
|
|
99
|
+
imageDataEnded = true;
|
|
100
|
+
if (type === "IHDR") {
|
|
101
|
+
if (offset !== 8 || header !== undefined)
|
|
102
|
+
throw new TypeError("Invalid PNG header order");
|
|
80
103
|
header = parseHeader(data);
|
|
104
|
+
}
|
|
105
|
+
else if (header === undefined)
|
|
106
|
+
throw new TypeError("Invalid PNG header order");
|
|
81
107
|
else if (type === "tRNS") {
|
|
82
|
-
if (
|
|
108
|
+
if (sawTransparency || compressed.length > 0)
|
|
109
|
+
throw new TypeError("Invalid PNG transparency order");
|
|
110
|
+
sawTransparency = true;
|
|
111
|
+
if (header.colorType === 2 && data.length === 6) {
|
|
112
|
+
transparentColor = [
|
|
113
|
+
data.readUInt16BE(0),
|
|
114
|
+
data.readUInt16BE(2),
|
|
115
|
+
data.readUInt16BE(4),
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
else if ((header.colorType === 0 && data.length === 2) ||
|
|
119
|
+
(header.colorType === 3 &&
|
|
120
|
+
sawPalette &&
|
|
121
|
+
data.length > 0 &&
|
|
122
|
+
data.length <= paletteEntries)) {
|
|
123
|
+
unsupportedReason ??=
|
|
124
|
+
"PNG transparency for this color type is not supported.";
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
83
127
|
throw new TypeError("Unsupported PNG transparency");
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (type === "PLTE") {
|
|
131
|
+
if (sawPalette ||
|
|
132
|
+
sawTransparency ||
|
|
133
|
+
compressed.length > 0 ||
|
|
134
|
+
length === 0 ||
|
|
135
|
+
length > 768 ||
|
|
136
|
+
length % 3 !== 0 ||
|
|
137
|
+
(header.colorType === 3 && length / 3 > 2 ** header.bitDepth) ||
|
|
138
|
+
(header.colorType !== 2 &&
|
|
139
|
+
header.colorType !== 3 &&
|
|
140
|
+
header.colorType !== 6))
|
|
141
|
+
throw new TypeError("Invalid PNG palette");
|
|
142
|
+
sawPalette = true;
|
|
143
|
+
paletteEntries = length / 3;
|
|
89
144
|
}
|
|
90
|
-
else if (type === "IDAT")
|
|
145
|
+
else if (type === "IDAT") {
|
|
146
|
+
if (imageDataEnded)
|
|
147
|
+
throw new TypeError("Nonconsecutive PNG image data");
|
|
91
148
|
compressed.push(data);
|
|
149
|
+
}
|
|
92
150
|
else if (type === "IEND") {
|
|
151
|
+
if (length !== 0 || dataEnd + 4 !== bytes.length)
|
|
152
|
+
throw new TypeError("Invalid PNG end chunk");
|
|
93
153
|
sawEnd = true;
|
|
94
154
|
break;
|
|
95
155
|
}
|
|
156
|
+
else if (/^[A-Z]/u.test(type)) {
|
|
157
|
+
unsupportedReason ??= `Unsupported critical PNG chunk ${type}.`;
|
|
158
|
+
}
|
|
96
159
|
offset = dataEnd + 4;
|
|
97
160
|
}
|
|
98
161
|
if (header === undefined || !sawEnd || compressed.length === 0)
|
|
99
162
|
throw new TypeError("Incomplete PNG");
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
163
|
+
if (header.colorType === 3 && !sawPalette)
|
|
164
|
+
throw new TypeError("Missing PNG palette");
|
|
165
|
+
if (unsupportedReason !== undefined)
|
|
166
|
+
throw new AnalysisUnsupportedTargetError("compare_web_screenshots", field, unsupportedReason);
|
|
167
|
+
if (!header.supported)
|
|
168
|
+
throw new AnalysisUnsupportedTargetError("compare_web_screenshots", field, "PNG encoding is not supported for pixel comparison.");
|
|
169
|
+
const pixels = BigInt(header.width) * BigInt(header.height);
|
|
170
|
+
const expectedRawBytes = (BigInt(header.width) * BigInt(header.channels) + 1n) *
|
|
171
|
+
BigInt(header.height);
|
|
107
172
|
return {
|
|
173
|
+
bytes,
|
|
108
174
|
width: header.width,
|
|
109
175
|
height: header.height,
|
|
110
|
-
|
|
176
|
+
channels: header.channels,
|
|
177
|
+
compressed,
|
|
178
|
+
transparentColor,
|
|
179
|
+
expectedRawBytes,
|
|
180
|
+
unfilteredBytes: pixels * BigInt(header.channels),
|
|
181
|
+
rgbaBytes: pixels * 4n,
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
const decodePng = (plan) => {
|
|
185
|
+
const expected = Number(plan.expectedRawBytes);
|
|
186
|
+
const raw = inflatePng(Buffer.concat(plan.compressed), expected + 1);
|
|
187
|
+
if (raw.byteLength !== expected)
|
|
188
|
+
throw new TypeError("Unexpected PNG size");
|
|
189
|
+
return {
|
|
190
|
+
width: plan.width,
|
|
191
|
+
height: plan.height,
|
|
192
|
+
rgba: expandRgba(unfilter(raw, plan.width, plan.height, plan.channels), plan.channels, plan.transparentColor),
|
|
111
193
|
};
|
|
112
194
|
};
|
|
195
|
+
const admitEncodedInputPair = (before, after) => {
|
|
196
|
+
const sourceBytes = BigInt(before.bytes) + BigInt(after.bytes);
|
|
197
|
+
if (sourceBytes > BigInt(PNG_COMPARISON_WORKING_MEMORY_BYTES))
|
|
198
|
+
throw pngWorkingMemoryError(sourceBytes, null, null);
|
|
199
|
+
};
|
|
200
|
+
const admitPngPair = (before, after) => {
|
|
201
|
+
// Input buffers remain live for both plans. For each decode, count the
|
|
202
|
+
// concatenated IDAT, rounded zlib output chunks, any concatenated output and
|
|
203
|
+
// unfiltered rows, plus RGB-to-RGBA output. The first completed RGBA image
|
|
204
|
+
// remains live while the second is decoded.
|
|
205
|
+
const inputBytes = BigInt(before.bytes.byteLength + after.bytes.byteLength);
|
|
206
|
+
const estimate = (current, retained) => {
|
|
207
|
+
const compressedBytes = current.compressed.reduce((total, chunk) => total + BigInt(chunk.byteLength), 0n);
|
|
208
|
+
const rgbaExpansion = current.channels === 3 ? current.rgbaBytes : 0n;
|
|
209
|
+
return (inputBytes +
|
|
210
|
+
(retained?.rgbaBytes ?? 0n) +
|
|
211
|
+
compressedBytes +
|
|
212
|
+
inflateBufferAllowance(current.expectedRawBytes) +
|
|
213
|
+
current.unfilteredBytes +
|
|
214
|
+
rgbaExpansion);
|
|
215
|
+
};
|
|
216
|
+
const estimateBytes = [
|
|
217
|
+
estimate(before, undefined),
|
|
218
|
+
estimate(after, before),
|
|
219
|
+
].reduce((maximum, value) => (value > maximum ? value : maximum), 0n);
|
|
220
|
+
if (estimateBytes > BigInt(PNG_COMPARISON_WORKING_MEMORY_BYTES))
|
|
221
|
+
throw pngWorkingMemoryError(estimateBytes, before, after);
|
|
222
|
+
};
|
|
223
|
+
const inflateBufferAllowance = (expectedRawBytes) => {
|
|
224
|
+
const chunkBytes = BigInt(PNG_INFLATE_CHUNK_BYTES);
|
|
225
|
+
const maximumOutputBytes = expectedRawBytes + 1n;
|
|
226
|
+
const roundUpToChunk = (bytes) => ((bytes + chunkBytes - 1n) / chunkBytes) * chunkBytes;
|
|
227
|
+
// Node checks maxOutputLength after writing a chunk, so a rejected stream can
|
|
228
|
+
// retain one chunk's worth of output past the limit before it throws.
|
|
229
|
+
const rejectedOutputChunks = roundUpToChunk(maximumOutputBytes + chunkBytes - 1n);
|
|
230
|
+
// Sync zlib retains each output chunk while Buffer.concat creates the final
|
|
231
|
+
// result. A full final chunk also allocates the next scratch chunk first.
|
|
232
|
+
const returnedOutputChunks = roundUpToChunk(maximumOutputBytes);
|
|
233
|
+
const scratchChunk = expectedRawBytes % chunkBytes === 0n ||
|
|
234
|
+
maximumOutputBytes % chunkBytes === 0n
|
|
235
|
+
? chunkBytes
|
|
236
|
+
: 0n;
|
|
237
|
+
const concatenatedOutput = maximumOutputBytes > chunkBytes ? maximumOutputBytes : 0n;
|
|
238
|
+
const returnedOutput = returnedOutputChunks + scratchChunk + concatenatedOutput;
|
|
239
|
+
return rejectedOutputChunks > returnedOutput
|
|
240
|
+
? rejectedOutputChunks
|
|
241
|
+
: returnedOutput;
|
|
242
|
+
};
|
|
243
|
+
const pngWorkingMemoryError = (estimateBytes, before, after) => new AnalysisResourceConstraintError("compare_web_screenshots", "memory", "Screenshot comparison exceeds REA's 256 MiB estimated working-memory budget.", {
|
|
244
|
+
boundary: "png-screenshot-comparison",
|
|
245
|
+
estimated_working_memory_bytes: estimateBytes.toString(),
|
|
246
|
+
maximum_working_memory_bytes: PNG_COMPARISON_WORKING_MEMORY_BYTES,
|
|
247
|
+
before_dimensions: before === null ? null : { width: before.width, height: before.height },
|
|
248
|
+
after_dimensions: after === null ? null : { width: after.width, height: after.height },
|
|
249
|
+
}, {
|
|
250
|
+
remediationAction: "Compare smaller screenshots or reduce their viewport dimensions before capture.",
|
|
251
|
+
});
|
|
252
|
+
const inflatePng = (compressed, maxOutputLength) => {
|
|
253
|
+
try {
|
|
254
|
+
return inflateSync(compressed, {
|
|
255
|
+
maxOutputLength,
|
|
256
|
+
chunkSize: PNG_INFLATE_CHUNK_BYTES,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
catch (cause) {
|
|
260
|
+
if (cause instanceof Error &&
|
|
261
|
+
"code" in cause &&
|
|
262
|
+
(cause.code === "Z_DATA_ERROR" ||
|
|
263
|
+
cause.code === "Z_BUF_ERROR" ||
|
|
264
|
+
cause.code === "ERR_BUFFER_TOO_LARGE"))
|
|
265
|
+
throw new TypeError("Invalid PNG image data", { cause });
|
|
266
|
+
throw cause;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
113
269
|
const parseHeader = (data) => {
|
|
114
270
|
if (data.byteLength !== 13)
|
|
115
271
|
throw new TypeError("Invalid PNG header");
|
|
116
272
|
const width = data.readUInt32BE(0);
|
|
117
273
|
const height = data.readUInt32BE(4);
|
|
118
|
-
const bitDepth = data[8];
|
|
119
|
-
const colorType = data[9];
|
|
274
|
+
const bitDepth = data[8] ?? 0;
|
|
275
|
+
const colorType = data[9] ?? -1;
|
|
276
|
+
const validDepth = (colorType === 0 && [1, 2, 4, 8, 16].includes(bitDepth)) ||
|
|
277
|
+
(colorType === 2 && [8, 16].includes(bitDepth)) ||
|
|
278
|
+
(colorType === 3 && [1, 2, 4, 8].includes(bitDepth)) ||
|
|
279
|
+
(colorType === 4 && [8, 16].includes(bitDepth)) ||
|
|
280
|
+
(colorType === 6 && [8, 16].includes(bitDepth));
|
|
120
281
|
if (width === 0 ||
|
|
121
282
|
height === 0 ||
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
283
|
+
width > 0x7fffffff ||
|
|
284
|
+
height > 0x7fffffff ||
|
|
285
|
+
!validDepth ||
|
|
125
286
|
data[10] !== 0 ||
|
|
126
287
|
data[11] !== 0 ||
|
|
127
|
-
data[12] !== 0)
|
|
128
|
-
throw new TypeError("
|
|
129
|
-
return {
|
|
288
|
+
(data[12] !== 0 && data[12] !== 1))
|
|
289
|
+
throw new TypeError("Invalid PNG header");
|
|
290
|
+
return {
|
|
291
|
+
width,
|
|
292
|
+
height,
|
|
293
|
+
colorType,
|
|
294
|
+
bitDepth,
|
|
295
|
+
interlace: data[12],
|
|
296
|
+
channels: colorType === 6 ? 4 : 3,
|
|
297
|
+
supported: bitDepth === 8 && (colorType === 2 || colorType === 6) && data[12] === 0,
|
|
298
|
+
};
|
|
130
299
|
};
|
|
131
300
|
const unfilter = (raw, width, height, channels) => {
|
|
132
301
|
const rowBytes = width * channels;
|
|
@@ -9,7 +9,7 @@ import { webSourceMapsSchema } from "../domain/webBundleAnalysis.js";
|
|
|
9
9
|
import { createWebTextArtifact } from "../domain/webContentArtifact.js";
|
|
10
10
|
import { safeParseJson } from "../domain/safeJson.js";
|
|
11
11
|
import { jsonParts } from "../domain/jsonSerialization.js";
|
|
12
|
-
import { inspectSourceMapValue, SourceMapFormatFailure, } from "../javascript/sourceMaps/SourceMapFormat.js";
|
|
12
|
+
import { inspectSourceMapValue, sourceMapJsonText, SourceMapFormatFailure, } from "../javascript/sourceMaps/SourceMapFormat.js";
|
|
13
13
|
import { WEB_SOURCE_MAP_LIMITS } from "../domain/webSourceLocation.js";
|
|
14
14
|
// Source maps are normally fetched as a small part of a larger inspection.
|
|
15
15
|
// Bound a stalled server to 30 seconds and bound raw map input retained for
|
|
@@ -106,6 +106,12 @@ class SourceMapEncodingError extends Error {
|
|
|
106
106
|
this.name = "SourceMapEncodingError";
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
class SourceMapRedirectLocationError extends Error {
|
|
110
|
+
constructor(url, location) {
|
|
111
|
+
super(`Source-map redirect from ${JSON.stringify(url)} supplied an invalid Location URL: ${JSON.stringify(location)}.`);
|
|
112
|
+
this.name = "SourceMapRedirectLocationError";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
109
115
|
const fetchOne = async (request, input, signal, host, budget) => {
|
|
110
116
|
if (!approvedUrl(request.fetchUrl, input.allowed_origins))
|
|
111
117
|
return emptySourceMapItem(request, "policy_filtered", "Declared source-map URL is outside the approved exact origins.");
|
|
@@ -131,13 +137,25 @@ const fetchOne = async (request, input, signal, host, budget) => {
|
|
|
131
137
|
throw cause;
|
|
132
138
|
if (cause instanceof SourceMapEncodingError)
|
|
133
139
|
return emptySourceMapItem(request, "invalid", cause.message);
|
|
134
|
-
return emptySourceMapItem(request, "fetch_failed", cause instanceof
|
|
140
|
+
return emptySourceMapItem(request, "fetch_failed", cause instanceof SourceMapRedirectLocationError ||
|
|
141
|
+
cause instanceof SourceMapSizeLimitError ||
|
|
142
|
+
cause instanceof SourceMapDeadlineError
|
|
135
143
|
? cause.message
|
|
136
|
-
:
|
|
137
|
-
? cause.message
|
|
138
|
-
: "Source-map fetch or validation failed.");
|
|
144
|
+
: "Source-map fetch or validation failed.");
|
|
139
145
|
}
|
|
140
146
|
};
|
|
147
|
+
/**
|
|
148
|
+
* Fetch redirect statuses per WHATWG Fetch (redirect status list:
|
|
149
|
+
* 301, 302, 303, 307, 308). Single owner for redirect decisions.
|
|
150
|
+
* 300/304/305/306 carry `Location` without being redirects — following
|
|
151
|
+
* them would replace the observed failure with an unrelated map.
|
|
152
|
+
* See https://fetch.spec.whatwg.org/#redirect-status
|
|
153
|
+
*/
|
|
154
|
+
export const isFetchRedirectStatus = (status) => status === 301 ||
|
|
155
|
+
status === 302 ||
|
|
156
|
+
status === 303 ||
|
|
157
|
+
status === 307 ||
|
|
158
|
+
status === 308;
|
|
141
159
|
const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signal, host) => {
|
|
142
160
|
let current = initialUrl;
|
|
143
161
|
const visited = new Set();
|
|
@@ -163,13 +181,21 @@ const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signa
|
|
|
163
181
|
await response.body?.cancel(signal.reason).catch(() => undefined);
|
|
164
182
|
throw signal.reason;
|
|
165
183
|
}
|
|
166
|
-
|
|
184
|
+
// `Location` is a redirect target only for Fetch redirect statuses.
|
|
185
|
+
// Other 3xx responses retain their own HTTP failure (strict identity:
|
|
186
|
+
// never replace the observed failure with an unrelated map).
|
|
187
|
+
if (!isFetchRedirectStatus(response.status))
|
|
167
188
|
return { response, fetchedUrl: current };
|
|
168
189
|
const location = response.headers.get("location");
|
|
169
190
|
if (location === null)
|
|
170
191
|
return { response, fetchedUrl: current };
|
|
171
192
|
await response.body?.cancel();
|
|
172
|
-
|
|
193
|
+
try {
|
|
194
|
+
current = new URL(location, current).href;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
throw new SourceMapRedirectLocationError(current, location);
|
|
198
|
+
}
|
|
173
199
|
}
|
|
174
200
|
};
|
|
175
201
|
const readBoundedText = async (response, budget, maxBytes, signal) => {
|
|
@@ -209,7 +235,7 @@ const readBoundedText = async (response, budget, maxBytes, signal) => {
|
|
|
209
235
|
offset += chunk.byteLength;
|
|
210
236
|
}
|
|
211
237
|
try {
|
|
212
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(joined);
|
|
238
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(joined);
|
|
213
239
|
}
|
|
214
240
|
catch {
|
|
215
241
|
throw new SourceMapEncodingError();
|
|
@@ -288,7 +314,7 @@ const promiseWithAbort = (promise, signal) => {
|
|
|
288
314
|
});
|
|
289
315
|
};
|
|
290
316
|
const normalizeSourceMap = (request, text, fetchedUrl, context) => {
|
|
291
|
-
const parsedJson = safeParseJson(text);
|
|
317
|
+
const parsedJson = safeParseJson(sourceMapJsonText(text));
|
|
292
318
|
if (!parsedJson.ok)
|
|
293
319
|
return emptySourceMapItem(request, "invalid", "Source-map JSON is not a version 3 map.");
|
|
294
320
|
const retainedBytesBeforeMap = context.budget.expandedBytes;
|
|
@@ -17,6 +17,7 @@ export class LocalWebScriptArtifacts {
|
|
|
17
17
|
async load(input, options) {
|
|
18
18
|
let field = ["manifest_path"];
|
|
19
19
|
let targetPath = input.manifest_path;
|
|
20
|
+
let callerSelected = true;
|
|
20
21
|
try {
|
|
21
22
|
const manifestBytes = await readWebArtifactJson(input.manifest_path, 32 * 1024 * 1024, options?.signal);
|
|
22
23
|
const manifest = webScriptExportManifestSchema.parse(manifestBytes.value);
|
|
@@ -34,6 +35,7 @@ export class LocalWebScriptArtifacts {
|
|
|
34
35
|
const root = resolve(dirname(input.manifest_path));
|
|
35
36
|
const sourcePath = join(root, "files", portable);
|
|
36
37
|
targetPath = sourcePath;
|
|
38
|
+
callerSelected = false;
|
|
37
39
|
await assertContained(root, sourcePath);
|
|
38
40
|
const sourceBytes = await readStableArtifact(sourcePath, 16 * 1024 * 1024, options?.signal);
|
|
39
41
|
await assertContained(root, sourcePath);
|
|
@@ -62,7 +64,7 @@ export class LocalWebScriptArtifacts {
|
|
|
62
64
|
});
|
|
63
65
|
}
|
|
64
66
|
catch (cause) {
|
|
65
|
-
return err(webArtifactReadError(cause, { operation: this.operation, field, targetPath }, options?.signal));
|
|
67
|
+
return err(webArtifactReadError(cause, { operation: this.operation, field, targetPath, callerSelected }, options?.signal));
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { Readable } from "node:stream";
|
|
4
|
+
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
|
5
|
+
import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js";
|
|
6
|
+
import { DESTINATION_CASE_COLLISION_PREFIX } from "../../artifacts/ArtifactPaths.js";
|
|
4
7
|
import { SafeOutputTree } from "../../artifacts/SafeOutputTree.js";
|
|
8
|
+
import { SafeOutputTreeCreationFailure } from "../../artifacts/SafeOutputTreeCreationFailure.js";
|
|
5
9
|
import { webScriptExportManifestSchema, webScriptExportResultSchema, } from "../../domain/webScriptExport.js";
|
|
6
|
-
import { planWebScriptExport } from "../../domain/webScriptExportPlan.js";
|
|
10
|
+
import { planWebScriptExport, } from "../../domain/webScriptExportPlan.js";
|
|
7
11
|
import { WebScriptExportError } from "../../domain/webScriptExportError.js";
|
|
8
12
|
const LIMITATIONS = [
|
|
9
13
|
"Only script bytes retained in this capture are exported. Sources are not refetched or executed, and a response or Debugger source does not prove execution.",
|
|
10
|
-
"Ordinary unambiguous URL paths preserve relative module layouts by origin. Query variants, collisions, inline sources, and unrepresentable paths are isolated;
|
|
14
|
+
"Ordinary unambiguous URL paths preserve relative module layouts by origin, including case-distinct spellings. Query variants, exact path collisions, file/directory prefixes, inline sources, and unrepresentable paths are isolated. A case-distinct pair is isolated only when the destination filesystem cannot store both spellings; the record names that pair. Browser module relationships of isolated paths remain unknown.",
|
|
11
15
|
"Local JavaScript analysis does not implement browser import maps, root-relative URL resolution, remote URL loading, or browser runtime behavior. It may strip import queries and fragments; isolated variants are not canonical targets.",
|
|
12
16
|
"Source-map declarations are retained as metadata. No source maps or missing dependencies are fetched or reconstructed.",
|
|
13
17
|
"Captured response bytes are browser-decoded bytes; Debugger sources are the exposed text encoded as UTF-8. Redacted bytes are exported exactly as retained, and may no longer parse as JavaScript.",
|
|
14
18
|
];
|
|
15
19
|
/** Exclusively publish verified bytes and a manifest, rolling back partial work. */
|
|
16
|
-
export const publishWebScripts = async (input, capture, captureSha256,
|
|
20
|
+
export const publishWebScripts = async (input, capture, captureSha256, options) => options.resources.run(async () => {
|
|
17
21
|
const planned = planWebScriptExport(capture.scripts);
|
|
18
|
-
|
|
22
|
+
let tree;
|
|
23
|
+
let result;
|
|
19
24
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
tree = await SafeOutputTree.create(input.output_directory);
|
|
26
|
+
options.signal?.throwIfAborted();
|
|
27
|
+
const records = [];
|
|
28
|
+
for (const [index, item] of planned.entries()) {
|
|
29
|
+
options.signal?.throwIfAborted();
|
|
30
|
+
records.push(await publishPlannedScript(tree, item, index, options.signal));
|
|
31
|
+
}
|
|
22
32
|
const manifest = webScriptExportManifestSchema.parse({
|
|
23
33
|
capture_path: input.capture_path,
|
|
24
34
|
capture_sha256: captureSha256,
|
|
@@ -42,7 +52,7 @@ export const publishWebScripts = async (input, capture, captureSha256, signal) =
|
|
|
42
52
|
});
|
|
43
53
|
const bytes = Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`);
|
|
44
54
|
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
45
|
-
|
|
55
|
+
result = webScriptExportResultSchema.parse({
|
|
46
56
|
...manifest,
|
|
47
57
|
manifest: {
|
|
48
58
|
path: join(tree.outputRoot, "manifest.json"),
|
|
@@ -50,25 +60,70 @@ export const publishWebScripts = async (input, capture, captureSha256, signal) =
|
|
|
50
60
|
bytes: bytes.length,
|
|
51
61
|
},
|
|
52
62
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (script.content.state === "captured" &&
|
|
56
|
-
record.content.state === "exported")
|
|
57
|
-
await tree.write(`files/${record.content.relative_path}`, Readable.from([script.content.bytes]), script.content.sha256, signal);
|
|
58
|
-
}
|
|
59
|
-
await tree.write("manifest.json", Readable.from([bytes]), digest, signal);
|
|
60
|
-
signal?.throwIfAborted();
|
|
63
|
+
await tree.write("manifest.json", Readable.from([bytes]), { sha256: digest, bytes: bytes.byteLength }, options.signal);
|
|
64
|
+
options.signal?.throwIfAborted();
|
|
61
65
|
await tree.commit();
|
|
62
66
|
return result;
|
|
63
67
|
}
|
|
64
68
|
catch (cause) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if (cause instanceof SafeOutputTreeCreationFailure)
|
|
70
|
+
tree = cause.tree;
|
|
71
|
+
if (tree !== undefined) {
|
|
72
|
+
const cleanup = await options.resources.release({
|
|
73
|
+
kind: "output-tree",
|
|
74
|
+
resource: tree.outputRoot,
|
|
75
|
+
tree,
|
|
76
|
+
});
|
|
77
|
+
if (cleanup.kind === "failed") {
|
|
78
|
+
const cleanupCause = cleanup.cause;
|
|
79
|
+
const diagnostic = tree.published
|
|
80
|
+
? `Publication completed, but descriptor cleanup failed (${message(cleanupCause)}). The published output remains available.`
|
|
81
|
+
: `Publication failed (${message(cause)}); rollback failed (${message(cleanupCause)}). Remove the residual output directory before retrying.`;
|
|
82
|
+
const error = new WebScriptExportError(cause instanceof ArtifactReaderFailure ? cause.reason : "io", tree.outputRoot, diagnostic, { residualPaths: [tree.outputRoot] });
|
|
83
|
+
if (tree.published && result !== undefined)
|
|
84
|
+
error.retainPartialObservation({
|
|
85
|
+
kind: "web-script-export",
|
|
86
|
+
result,
|
|
87
|
+
});
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
if (tree.published && result !== undefined)
|
|
91
|
+
return result;
|
|
70
92
|
}
|
|
71
93
|
throw cause;
|
|
72
94
|
}
|
|
95
|
+
});
|
|
96
|
+
const publishPlannedScript = async (tree, item, index, signal) => {
|
|
97
|
+
const { script, record } = item;
|
|
98
|
+
const content = script.content;
|
|
99
|
+
if (content.state !== "captured" || record.content.state !== "exported")
|
|
100
|
+
return record;
|
|
101
|
+
const write = (relativePath) => tree.write(`files/${relativePath}`, Readable.from([content.bytes]), { sha256: content.sha256, bytes: content.bytes.byteLength }, signal);
|
|
102
|
+
try {
|
|
103
|
+
await write(record.content.relative_path);
|
|
104
|
+
return record;
|
|
105
|
+
}
|
|
106
|
+
catch (cause) {
|
|
107
|
+
const collision = destinationCollisionReason(cause);
|
|
108
|
+
if (collision === undefined || record.content.layout !== "url-path")
|
|
109
|
+
throw cause;
|
|
110
|
+
const relativePath = isolatedScriptPath(script, index);
|
|
111
|
+
await write(relativePath);
|
|
112
|
+
return {
|
|
113
|
+
...record,
|
|
114
|
+
content: {
|
|
115
|
+
...record.content,
|
|
116
|
+
relative_path: relativePath,
|
|
117
|
+
layout: "isolated",
|
|
118
|
+
layout_reason: collision,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
73
122
|
};
|
|
123
|
+
const isolatedScriptPath = (script, index) => `isolated/source-${index + 1}-${createHash("sha256").update(JSON.stringify(script.source)).digest("hex")}.js`;
|
|
124
|
+
const destinationCollisionReason = (cause) => cause instanceof ArtifactReaderFailure &&
|
|
125
|
+
cause.reason === "path" &&
|
|
126
|
+
cause.message.startsWith(DESTINATION_CASE_COLLISION_PREFIX)
|
|
127
|
+
? cause.message
|
|
128
|
+
: undefined;
|
|
74
129
|
const message = (cause) => cause instanceof Error ? cause.message : "Unknown publication failure";
|
|
@@ -14,9 +14,9 @@ const indexResponses = (events) => {
|
|
|
14
14
|
requests: new Map(),
|
|
15
15
|
};
|
|
16
16
|
for (const event of events) {
|
|
17
|
-
if (event.kind === "request"
|
|
17
|
+
if (event.kind === "request")
|
|
18
18
|
index.requests.set(event.transaction_id, (index.requests.get(event.transaction_id) ?? 0) + 1);
|
|
19
|
-
if (event.kind === "response"
|
|
19
|
+
if (event.kind === "response")
|
|
20
20
|
append(index.responses, event.transaction_id, event);
|
|
21
21
|
if (event.kind === "network-content" && event.phase === "response")
|
|
22
22
|
append(index.contents, event.source_event_sequence, event);
|
|
@@ -25,33 +25,29 @@ const indexResponses = (events) => {
|
|
|
25
25
|
};
|
|
26
26
|
const projectRequest = (request, index) => {
|
|
27
27
|
const id = request.transaction_id;
|
|
28
|
-
const matches =
|
|
28
|
+
const matches = index.responses.get(id) ?? [];
|
|
29
29
|
const response = matches.length === 1 ? matches[0] : undefined;
|
|
30
30
|
const bodies = response === undefined ? [] : (index.contents.get(response.sequence) ?? []);
|
|
31
31
|
const body = bodies.length === 1 ? bodies[0]?.body : undefined;
|
|
32
|
-
const ambiguous =
|
|
33
|
-
matches.length > 1 ||
|
|
34
|
-
bodies.length > 1;
|
|
32
|
+
const ambiguous = index.requests.get(id) !== 1 || matches.length > 1 || bodies.length > 1;
|
|
35
33
|
return {
|
|
36
34
|
source: {
|
|
37
35
|
kind: "scenario-response",
|
|
38
|
-
transaction_id: id
|
|
36
|
+
transaction_id: id,
|
|
39
37
|
request_sequence: request.sequence,
|
|
40
38
|
response_sequence: ambiguous ? null : (response?.sequence ?? null),
|
|
41
39
|
status: ambiguous ? null : (response?.status ?? null),
|
|
42
40
|
},
|
|
43
41
|
url: request.url.url,
|
|
44
|
-
content: projectBody(body,
|
|
42
|
+
content: projectBody(body, ambiguous),
|
|
45
43
|
};
|
|
46
44
|
};
|
|
47
45
|
const unavailable = (reason, message) => ({ state: "unavailable", reason, message });
|
|
48
|
-
const projectBody = (body,
|
|
46
|
+
const projectBody = (body, ambiguous) => {
|
|
49
47
|
if (ambiguous)
|
|
50
48
|
return unavailable("ambiguous-transaction", "The capture does not identify one request, response, and content record for this transaction.");
|
|
51
49
|
if (body === undefined)
|
|
52
|
-
return unavailable(
|
|
53
|
-
? "transaction-identity-unavailable"
|
|
54
|
-
: "response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
|
|
50
|
+
return unavailable("response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
|
|
55
51
|
if (body.state === "unavailable")
|
|
56
52
|
return unavailable(body.reason, body.message);
|
|
57
53
|
if (body.state !== "captured")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
|
3
3
|
import { readStableArtifact } from "../../artifacts/readStableArtifact.js";
|
|
4
|
-
import { AnalysisCancelledError, AnalysisInputError, } from "../../domain/analysisErrorCore.js";
|
|
4
|
+
import { AnalysisAccessDeniedError, AnalysisCancelledError, AnalysisInputError, } from "../../domain/analysisErrorCore.js";
|
|
5
5
|
import { ArtifactOperationError } from "../../domain/artifactOperationError.js";
|
|
6
6
|
import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
|
|
7
7
|
import { safeParseJson } from "../../domain/safeJson.js";
|
|
@@ -29,6 +29,11 @@ export const readWebArtifactJson = async (path, maximumBytes, signal) => {
|
|
|
29
29
|
export const webArtifactReadError = (cause, context, signal) => {
|
|
30
30
|
if (signal?.aborted === true)
|
|
31
31
|
return new AnalysisCancelledError(context.operation);
|
|
32
|
+
const selection = context.callerSelected
|
|
33
|
+
? selectedFileError(cause, context)
|
|
34
|
+
: undefined;
|
|
35
|
+
if (selection !== undefined)
|
|
36
|
+
return selection;
|
|
32
37
|
if (cause instanceof ArtifactReaderFailure)
|
|
33
38
|
return new ArtifactOperationError(context.operation, cause.reason, cause.details, cause.message);
|
|
34
39
|
if (cause instanceof Error &&
|
|
@@ -54,3 +59,20 @@ export const webArtifactReadError = (cause, context, signal) => {
|
|
|
54
59
|
},
|
|
55
60
|
});
|
|
56
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* Report a missing, non-regular or unreadable caller-selected file as the
|
|
64
|
+
* caller's selection or a host permission denial, not an artifact fault.
|
|
65
|
+
*/
|
|
66
|
+
const selectedFileError = (cause, context) => {
|
|
67
|
+
const selected = (message) => new AnalysisInputError(context.operation, { cause }, [
|
|
68
|
+
{ path: context.field, reason: "invalid_value", message },
|
|
69
|
+
]);
|
|
70
|
+
if (cause instanceof ArtifactReaderFailure)
|
|
71
|
+
return cause.reason === "path" ? selected(cause.message) : undefined;
|
|
72
|
+
const code = cause instanceof Error && "code" in cause ? String(cause.code) : "";
|
|
73
|
+
if (code === "EACCES" || code === "EPERM")
|
|
74
|
+
return new AnalysisAccessDeniedError(context.operation, context.targetPath, code, { cause });
|
|
75
|
+
if (code === "ENOENT" || code === "ENOTDIR")
|
|
76
|
+
return selected(`Selected file could not be read (${code}): ${context.targetPath}`);
|
|
77
|
+
return undefined;
|
|
78
|
+
};
|
|
@@ -69,9 +69,9 @@ export const captureWebExecution = async (input, sources) => {
|
|
|
69
69
|
sources.check();
|
|
70
70
|
const verifiedRequests = requests.result();
|
|
71
71
|
const verifiedMainScripts = mainScripts.filter((id) => sources.belongsToDocument(id));
|
|
72
|
-
const sample =
|
|
73
|
-
?
|
|
74
|
-
:
|
|
72
|
+
const sample = parsed?.success === true
|
|
73
|
+
? normalizePreciseCoverage(parsed.data, sources, retained)
|
|
74
|
+
: undefined;
|
|
75
75
|
await session.options.progress?.report({
|
|
76
76
|
phase: "browser_execution",
|
|
77
77
|
completed: 2,
|