rea-agents 6.3.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +51 -19
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +22 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +70 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +66 -31
- package/dist/application/DirectAnalysis.js +2 -2
- package/dist/application/DirectAnalysisCleanup.js +1 -1
- package/dist/application/DirectAnalysisStatus.js +1 -1
- package/dist/application/Doctor.js +5 -3
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +6 -0
- package/dist/application/JsonFiles.js +6 -5
- package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
- package/dist/application/LinuxHopper.js +4 -12
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +9 -3
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +93 -7
- package/dist/application/Setup.js +54 -6
- package/dist/application/SetupClientConfiguration.js +116 -16
- package/dist/application/SetupHost.js +102 -24
- package/dist/application/SetupPlan.js +5 -8
- package/dist/application/SetupSkill.js +58 -39
- package/dist/application/SupportedClients.js +290 -65
- package/dist/application/Uninstall.js +158 -10
- package/dist/application/UpdateMaintenance.js +17 -21
- package/dist/application/Utf8JsonInput.js +7 -0
- package/dist/application/WebScriptExportService.js +131 -65
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/BinarySession.js +2 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
- package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +20 -15
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +176 -102
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
- package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +75 -32
- package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +62 -25
- package/dist/artifacts/inventory/scanReader.js +38 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +5 -0
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +32 -10
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
- package/dist/browser/PlaywrightScenarioSession.js +127 -54
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +3 -3
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreBinaryCommands.js +0 -5
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +6 -1
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +17 -1
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +11 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/utilityCommands.js +66 -18
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +6 -0
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +2 -2
- package/dist/cliObservationOptions.js +3 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/directAnalysis.js +12 -4
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +10 -10
- package/dist/contracts/javascript/electronToolContracts.js +15 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionToolContracts.js +2 -2
- package/dist/contracts/sessionToolSchemas.js +6 -2
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -3
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -6
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +2 -1
- package/dist/domain/analysisView/analysisView.js +52 -2
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +2 -2
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +35 -7
- package/dist/domain/artifactGraph.js +5 -3
- package/dist/domain/artifactIdentity.js +30 -2
- package/dist/domain/artifactInspection.js +3 -43
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +11 -12
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/evidence.js +2 -1
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
- package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
- package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
- package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
- package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
- package/dist/domain/javascript/javascriptAstValues.js +32 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
- package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
- package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
- package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonShape.js +63 -52
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/managed/managedApplicationGraph.js +37 -0
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +91 -1
- package/dist/domain/process/processCaptureExample.js +24 -0
- package/dist/domain/process/processCaptureValidation.js +79 -0
- package/dist/domain/process/processScenario.js +59 -7
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/referenceSourceGraph.js +25 -16
- package/dist/domain/referenceSourceImportParsing.js +6 -3
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/webBundleAnalyzerInspection.js +14 -2
- package/dist/domain/webCaptureDiff.js +102 -4
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +55 -24
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +33 -1
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +76 -4
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +1 -1
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +80 -39
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +8 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +3 -1
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/NativeMacOSProvider.js +91 -16
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +96 -39
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +28 -4
- package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessHarness.js +194 -26
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +97 -25
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +32 -3
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +49 -18
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +33 -5
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
|
@@ -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
|
|
@@ -235,7 +235,7 @@ const readBoundedText = async (response, budget, maxBytes, signal) => {
|
|
|
235
235
|
offset += chunk.byteLength;
|
|
236
236
|
}
|
|
237
237
|
try {
|
|
238
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(joined);
|
|
238
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(joined);
|
|
239
239
|
}
|
|
240
240
|
catch {
|
|
241
241
|
throw new SourceMapEncodingError();
|
|
@@ -314,7 +314,7 @@ const promiseWithAbort = (promise, signal) => {
|
|
|
314
314
|
});
|
|
315
315
|
};
|
|
316
316
|
const normalizeSourceMap = (request, text, fetchedUrl, context) => {
|
|
317
|
-
const parsedJson = safeParseJson(text);
|
|
317
|
+
const parsedJson = safeParseJson(sourceMapJsonText(text));
|
|
318
318
|
if (!parsedJson.ok)
|
|
319
319
|
return emptySourceMapItem(request, "invalid", "Source-map JSON is not a version 3 map.");
|
|
320
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";
|
|
@@ -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,
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { AnalysisOutputError } from "../../domain/analysisErrorCore.js";
|
|
2
|
-
import { preciseCoverageSchema } from "./CdpRuntimeProtocol.js";
|
|
3
2
|
/** Validate source-range bounds against exact retained UTF-16 text without flattening nested counts. */
|
|
4
|
-
export const normalizePreciseCoverage = (
|
|
5
|
-
const
|
|
6
|
-
if (!parsed.success)
|
|
7
|
-
throw new AnalysisOutputError(sources.session.operation, `Malformed precise coverage: ${parsed.error.message}`);
|
|
3
|
+
export const normalizePreciseCoverage = (parsed, sources, retained) => {
|
|
4
|
+
const retainedSources = new Map(retained.map(({ script_id, source }) => [script_id, source]));
|
|
8
5
|
const scripts = [];
|
|
9
6
|
let excluded = 0;
|
|
10
|
-
for (const script of parsed.
|
|
7
|
+
for (const script of parsed.result) {
|
|
11
8
|
if (!sources.belongsToDocument(script.scriptId)) {
|
|
12
9
|
excluded += 1;
|
|
13
10
|
continue;
|
|
14
11
|
}
|
|
15
|
-
const source =
|
|
12
|
+
const source = retainedSources.get(script.scriptId);
|
|
16
13
|
scripts.push({
|
|
17
14
|
script_id: script.scriptId,
|
|
18
15
|
reported_url: sources.sourceUrl(script.scriptId, script.url),
|
|
@@ -35,7 +32,7 @@ export const normalizePreciseCoverage = (raw, sources, retained) => {
|
|
|
35
32
|
});
|
|
36
33
|
}
|
|
37
34
|
return {
|
|
38
|
-
timestamp: parsed.
|
|
35
|
+
timestamp: parsed.timestamp,
|
|
39
36
|
coverage: {
|
|
40
37
|
state: "captured",
|
|
41
38
|
reason: null,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { TextDecoder } from "node:util";
|
|
2
3
|
import { isSafeNumber, LosslessNumber } from "lossless-json";
|
|
3
4
|
import { parseHarJson } from "./HarJson.js";
|
|
4
5
|
import { WEB_NETWORK_CAPTURE_LIMITS, } from "../../domain/webNetworkCapture.js";
|
|
@@ -6,6 +7,19 @@ import { CaptureFormatError } from "./CaptureFormatError.js";
|
|
|
6
7
|
import { CaptureRedaction, captureObject, capturePointer, } from "./CaptureRedaction.js";
|
|
7
8
|
import { createHarValidator } from "./HarSchema.js";
|
|
8
9
|
import { HAR_CAPTURE_PROVIDER_IDENTITY } from "./CaptureRelease.js";
|
|
10
|
+
/**
|
|
11
|
+
* Decode retained HAR bytes as UTF-8. HAR 1.2 lets writers emit a byte-order
|
|
12
|
+
* mark and requires readers to ignore it, so one leading BOM is skipped.
|
|
13
|
+
*/
|
|
14
|
+
export const decodeHarText = (bytes) => {
|
|
15
|
+
try {
|
|
16
|
+
// ignoreBOM: false (the default) is what skips the mark; true keeps it.
|
|
17
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new CaptureFormatError("format", "HAR is not valid UTF-8 JSON.");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
9
23
|
/** Decode a retained HAR with exact numeric lexemes and unchanged upstream schema validation. */
|
|
10
24
|
export const decodeHarCapture = (text, sensitiveValues) => {
|
|
11
25
|
const raw = parseHarJson(text);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { TextDecoder } from "node:util";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { readStableArtifact } from "../../artifacts/readStableArtifact.js";
|
|
5
4
|
import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js";
|
|
6
5
|
import { CaptureFormatError } from "./CaptureFormatError.js";
|
|
7
|
-
import { decodeHarCapture } from "./HarCapture.js";
|
|
6
|
+
import { decodeHarCapture, decodeHarText } from "./HarCapture.js";
|
|
8
7
|
const requestSchema = z.strictObject({
|
|
9
8
|
snapshot_path: z.string(),
|
|
10
9
|
reply_path: z.string(),
|
|
@@ -16,16 +15,9 @@ const main = async () => {
|
|
|
16
15
|
let reply;
|
|
17
16
|
try {
|
|
18
17
|
const snapshot = await readStableArtifact(request.snapshot_path, WEB_NETWORK_CAPTURE_LIMITS.inputBytes);
|
|
19
|
-
let text;
|
|
20
|
-
try {
|
|
21
|
-
text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(snapshot.bytes);
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
throw new CaptureFormatError("format", "HAR is not valid UTF-8 JSON.");
|
|
25
|
-
}
|
|
26
18
|
reply = {
|
|
27
19
|
ok: true,
|
|
28
|
-
value: decodeHarCapture(
|
|
20
|
+
value: decodeHarCapture(decodeHarText(snapshot.bytes), request.sensitive_values),
|
|
29
21
|
};
|
|
30
22
|
}
|
|
31
23
|
catch (cause) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access } from "node:fs/promises";
|
|
1
|
+
import { access, stat } from "node:fs/promises";
|
|
2
2
|
import { constants } from "node:fs";
|
|
3
3
|
import { isAbsolute } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -22,6 +22,8 @@ export class MitmproxyCaptureAdapter {
|
|
|
22
22
|
throw new AnalysisCapabilityUnavailableError("mitmproxy", OPERATION, MITMDUMP_REQUIREMENT, { userMessage: MITMDUMP_REQUIREMENT });
|
|
23
23
|
try {
|
|
24
24
|
await access(command, constants.R_OK | constants.X_OK);
|
|
25
|
+
if (!(await stat(command)).isFile())
|
|
26
|
+
throw new TypeError("Configured path is not a regular file");
|
|
25
27
|
}
|
|
26
28
|
catch (cause) {
|
|
27
29
|
const reason = `Configured mitmdump executable is unavailable: ${command}.`;
|