rea-agents 6.0.0 → 6.2.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 +26 -18
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +205 -51
- package/bridge/hopper_bridge.py +314 -127
- package/bridge/mitmproxy/capture.py +0 -2
- package/bridge/native/rea_lldb_tracer.py +630 -94
- package/bridge/process/ProcessRunTokenReader.swift +39 -5
- package/bridge/pwntools/recorded_crash_impl.py +4 -0
- package/dist/android/JadxConfiguration.js +274 -31
- package/dist/android/JadxMcpTransport.js +18 -2
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +76 -37
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/BinaryTargetResolver.js +5 -3
- package/dist/application/BrowserEvidence.js +3 -8
- package/dist/application/BrowserScenarioEvidence.js +2 -18
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +48 -11
- package/dist/application/ClientConfigurationDocument.js +917 -8
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +56 -51
- package/dist/application/DirectAnalysisCleanup.js +72 -0
- package/dist/application/DirectAnalysisStatus.js +4 -5
- package/dist/application/Doctor.js +19 -21
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +64 -17
- package/dist/application/EvidenceBundleFiles.js +30 -13
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +11 -2
- package/dist/application/JsonFiles.js +83 -28
- package/dist/application/LinuxHopper.js +9 -6
- package/dist/application/MacHopper.js +15 -18
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/RealHopperAssertions.js +0 -11
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +1 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/ReferenceSourceImportEntries.js +1 -1
- package/dist/application/Setup.js +21 -17
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +21 -29
- package/dist/application/SetupPlan.js +11 -9
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +82 -29
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateMaintenance.js +7 -5
- package/dist/application/UpdateRuntime.js +57 -36
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCaptureService.js +4 -2
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +32 -6
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WorkflowEvidence.js +105 -0
- package/dist/application/XrefsAddressResolution.js +45 -0
- package/dist/application/analysisView/AnalysisViewService.js +76 -0
- package/dist/application/binary/AnalysisClientCleanup.js +30 -5
- package/dist/application/binary/AnalysisProviderEvaluation.js +22 -7
- package/dist/application/binary/AnalysisProviderRegistry.js +4 -6
- package/dist/application/binary/AnalysisSnapshotCache.js +13 -14
- package/dist/application/binary/BinarySession.js +161 -93
- package/dist/application/binary/BinarySessionComposition.js +1 -3
- package/dist/application/binary/BinarySessionExecution.js +3 -5
- package/dist/application/binary/BinarySessionOpen.js +4 -4
- package/dist/application/binary/BinarySessionRecords.js +26 -4
- package/dist/application/binary/BinarySessionStatus.js +18 -7
- package/dist/application/binary/CompositeProvider.js +16 -17
- package/dist/application/binary/LazyAnalysisProvider.js +8 -5
- package/dist/application/binary/SessionProviderRouter.js +27 -135
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
- package/dist/application/evm/EvmInterfaceService.js +4 -2
- package/dist/application/homebrew.js +48 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +21 -4
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +27 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +10 -7
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +44 -10
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +49 -19
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +56 -8
- package/dist/application/javascript/JavaScriptModuleRelationships.js +38 -9
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +6 -4
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +64 -19
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +9 -5
- package/dist/application/managed/ManagedNativeVerificationService.js +6 -4
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/process/ProcessCli.js +25 -17
- package/dist/application/process/ProcessEvidence.js +4 -4
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +48 -13
- package/dist/artifacts/ArtifactReader.js +31 -0
- package/dist/artifacts/DirectoryArtifactReader.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +106 -15
- package/dist/artifacts/NativeDmgArtifactReader.js +73 -21
- package/dist/artifacts/SafeOutputTree.js +16 -2
- package/dist/artifacts/ZipArtifactReader.js +11 -4
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +26 -5
- package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +55 -23
- package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/artifacts/extraction/ArtifactExtraction.js +78 -21
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +79 -68
- package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
- package/dist/artifacts/inventory/reader.js +3 -3
- package/dist/artifacts/inventory/scanCanonical.js +59 -38
- package/dist/artifacts/inventory/scanReader.js +5 -9
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
- package/dist/browser/CdpBrowserProvider.js +2 -3
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +78 -15
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -1
- package/dist/browser/CdpCaptureValues.js +20 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpElectronProvider.js +0 -2
- package/dist/browser/CdpElectronScriptEvents.js +2 -8
- package/dist/browser/CdpElectronScripts.js +2 -3
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/CdpPageCaptureScripts.js +2 -3
- package/dist/browser/CdpSafeMetadata.js +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
- package/dist/browser/PlaywrightElectronActiveActions.js +34 -79
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +133 -130
- package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
- package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
- package/dist/browser/PlaywrightScenarioEvents.js +1 -1
- package/dist/browser/PlaywrightScenarioSession.js +39 -22
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
- package/dist/browser/history/CaptureFailures.js +41 -1
- package/dist/browser/history/CaptureRelease.js +5 -0
- package/dist/browser/history/HarCaptureAdapter.js +3 -3
- package/dist/browser/history/HarJson.js +3 -2
- package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
- package/dist/browser/history/MitmproxyCaptureAdapter.js +4 -2
- package/dist/catalogIdentity.js +0 -1
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/analysisViewCommands.js +36 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +11 -12
- package/dist/cli/coreAnalysisCommands.js +3 -3
- package/dist/cli/coreBinaryCommands.js +100 -37
- package/dist/cli/coreNativeCommands.js +9 -10
- package/dist/cli/electronCommands.js +10 -9
- package/dist/cli/interactiveSetup.js +6 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/managedCommands.js +7 -8
- package/dist/cli/nativeCallCommands.js +3 -5
- package/dist/cli/omittableDefaults.js +50 -0
- package/dist/cli/processCommands.js +3 -2
- package/dist/cli/setupCommands.js +16 -15
- package/dist/cli/utilityCommands.js +9 -9
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +18 -9
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +1 -1
- package/dist/cliJsonInput.js +24 -5
- package/dist/cliOutput.js +0 -38
- package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
- package/dist/composition/binary.js +9 -9
- package/dist/composition/browserScenario.js +2 -1
- package/dist/composition/directAnalysis.js +20 -13
- package/dist/composition/electronScenario.js +1 -1
- package/dist/composition/optionalObservationProviders.js +12 -7
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraStartupTimeout.js +12 -0
- package/dist/config/homeDirectory.js +12 -0
- package/dist/config/mcpResponseBudget.js +30 -0
- package/dist/config/parseConfig.js +8 -3
- package/dist/config/parsers.js +19 -22
- package/dist/contracts/analysisViewToolContracts.js +56 -0
- package/dist/contracts/applicationToolContracts.js +5 -4
- package/dist/contracts/artifactComparisonExample.js +2 -2
- package/dist/contracts/artifactToolContracts.js +1 -1
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +19 -15
- package/dist/contracts/enhancedInputs.js +7 -5
- package/dist/contracts/enhancedToolContracts.js +7 -6
- package/dist/contracts/evm/evmToolContracts.js +1 -1
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/inputSchemaPresentation.js +90 -0
- package/dist/contracts/investigationExamples.js +4 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -2
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
- package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +7 -14
- package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
- package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
- package/dist/contracts/native/nativeToolContracts.js +5 -3
- package/dist/contracts/officialToolContracts.js +16 -16
- package/dist/contracts/promptContracts.js +5 -5
- package/dist/contracts/providerSelection.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +18 -8
- package/dist/contracts/sessionToolSchemas.js +3 -19
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +2 -0
- package/dist/contracts/toolEffects.js +1 -1
- package/dist/contracts/toolOutputSchemaGroups.js +160 -115
- package/dist/contracts/toolOutputSchemaPrimitives.js +28 -20
- package/dist/contracts/toolSchemaMetadata.js +41 -33
- package/dist/contracts/webNetworkCaptureToolContracts.js +2 -2
- package/dist/contracts/webRuntimeToolContracts.js +1 -1
- package/dist/contracts/webScriptToolContracts.js +1 -1
- package/dist/doctorRuntime.js +7 -5
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +6 -1
- package/dist/domain/analysisErrorPresentation.js +90 -20
- package/dist/domain/analysisErrorProjection.js +130 -32
- package/dist/domain/analysisSnapshot.js +29 -31
- package/dist/domain/analysisView/analysisView.js +243 -0
- package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
- package/dist/domain/analysisView/binaryLayoutView.js +159 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +18 -10
- package/dist/domain/apple/appleApplication.js +42 -15
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dylibResolution.js +130 -12
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -14
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +35 -3
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactComparison.js +15 -6
- package/dist/domain/artifactGraph.js +16 -3
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +28 -40
- package/dist/domain/artifactOperationError.js +3 -3
- package/dist/domain/artifactPartialObservation.js +1 -0
- package/dist/domain/artifactPathSyntax.js +49 -0
- package/dist/domain/binaryTarget.js +39 -13
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCaptureComparison.js +13 -49
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserNetworkEvidence.js +10 -4
- package/dist/domain/browserObservation.js +0 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +14 -3
- package/dist/domain/browserScenario.js +0 -1
- package/dist/domain/browserScenarioCapture.js +1 -2
- package/dist/domain/browserScenarioDiff.js +0 -2
- package/dist/domain/browserScenarioDiffEvidence.js +0 -12
- package/dist/domain/browserScenarioDiffValues.js +2 -2
- package/dist/domain/browserScenarioValues.js +5 -10
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPath.js +8 -9
- package/dist/domain/callPathSchemas.js +2 -2
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/completionLedgerGeneration.js +2 -1
- package/dist/domain/configurationErrors.js +13 -1
- package/dist/domain/conformancePackage.js +4 -3
- package/dist/domain/evidence.js +65 -36
- package/dist/domain/evidenceBundle.js +47 -8
- package/dist/domain/evidenceCompletionLedger.js +2 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/explicitSensitiveFailure.js +17 -1
- package/dist/domain/firmware/firmwareAnalysis.js +6 -7
- package/dist/domain/functionComparison.js +4 -5
- package/dist/domain/functionComparisonDimensions.js +120 -87
- package/dist/domain/functionComparisonNormalization.js +23 -34
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/functionComparisonSchemas.js +2 -8
- package/dist/domain/functionDossierEvidence.js +2 -37
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +47 -64
- package/dist/domain/javascript/electronObservation.js +14 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +39 -3
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
- package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
- package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
- package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
- package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
- package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +106 -5
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +23 -6
- package/dist/domain/javascript/javascriptSemanticGraph.js +98 -43
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +18 -21
- package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
- package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
- package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +126 -61
- package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +16 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -17
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
- package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +90 -6
- package/dist/domain/localPath.js +6 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedArtifact.js +6 -4
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparison.js +2 -9
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -11
- package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
- package/dist/domain/native/binaryLayout.js +2 -3
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeApiBoundary.js +1 -1
- package/dist/domain/native/nativeCallObservation.js +37 -13
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/nativeInstruction.js +7 -0
- package/dist/domain/native/recordedCrash.js +2 -3
- package/dist/domain/offsetDateTime.js +17 -0
- package/dist/domain/process/processCapture.js +21 -16
- package/dist/domain/process/processCaptureCoverage.js +67 -0
- package/dist/domain/process/processCaptureExample.js +2 -1
- package/dist/domain/process/processCaptureParsing.js +1 -34
- package/dist/domain/process/processCaptureValidation.js +81 -13
- package/dist/domain/process/processComparison.js +79 -26
- package/dist/domain/process/processObservation.js +10 -2
- package/dist/domain/process/processScenario.js +35 -12
- package/dist/domain/process/processTraceComparison.js +0 -2
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +15 -11
- package/dist/domain/process/processTraceSpecification.js +3 -4
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +3 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/reconstructionCoverage.js +5 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
- package/dist/domain/reconstructionReadinessSchemas.js +2 -1
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +4 -3
- package/dist/domain/referenceSourceGraph.js +20 -21
- package/dist/domain/staticRuntimeCorrelation.js +8 -45
- package/dist/domain/stringPatterns.js +6 -0
- package/dist/domain/swiftSymbolClassification.js +61 -0
- package/dist/domain/symbolAnalysis.js +66 -18
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +0 -1
- package/dist/domain/webCaptureDiffSchemas.js +6 -3
- package/dist/domain/webEventListeners.js +3 -2
- package/dist/domain/webExecution.js +3 -2
- package/dist/domain/webRuntime.js +19 -7
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedArtifactInspector.js +2 -19
- package/dist/dotnet/ManagedMemberInspector.js +12 -18
- package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
- package/dist/dotnet/ManagedMemberRows.js +75 -62
- package/dist/dotnet/ManagedMetadataInventory.js +16 -22
- package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
- package/dist/dotnet/ManagedReaderFailure.js +16 -0
- package/dist/dotnet/ManagedStaticProvider.js +3 -5
- package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
- package/dist/evaluation/AgentEvaluationReport.js +28 -0
- package/dist/evaluation/CodexAgentEval.js +12 -8
- package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
- package/dist/evm/EvmoleInterfaceProvider.js +2 -1
- package/dist/firmware/FirmwareCommand.js +9 -5
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/firmware/FirmwareProvider.js +4 -4
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +7 -5
- package/dist/ghidra/GhidraClient.js +126 -34
- package/dist/ghidra/GhidraClientStartup.js +0 -2
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraDoctor.js +6 -5
- package/dist/ghidra/GhidraFunctionValues.js +13 -12
- package/dist/ghidra/GhidraInstallation.js +58 -33
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +66 -0
- package/dist/ghidra/GhidraLauncher.js +47 -22
- package/dist/ghidra/GhidraProvider.js +6 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +20 -2
- package/dist/ghidra/GhidraProviderClient.js +36 -15
- package/dist/ghidra/GhidraSessionError.js +13 -7
- package/dist/ghidra/GhidraSessionRoot.js +39 -0
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
- package/dist/hopper/BridgeLauncher.js +65 -56
- package/dist/hopper/HopperAnalysisProfile.js +65 -12
- package/dist/hopper/HopperCleanup.js +63 -22
- package/dist/hopper/HopperClient.js +288 -59
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +197 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +71 -19
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +134 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +133 -49
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
- package/dist/ida/IdaConfiguration.js +8 -3
- package/dist/ida/IdaInput.js +1 -7
- package/dist/ida/IdaMcpConnection.js +8 -4
- package/dist/ida/IdaOperationRunner.js +3 -3
- package/dist/ida/IdaProvider.js +8 -12
- package/dist/ida/IdaSessionClient.js +20 -18
- package/dist/ida/IdaWorkspace.js +12 -13
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +9 -4
- package/dist/inspector/V8InspectorProvider.js +82 -36
- package/dist/javascript/recovery/WakaruCommand.js +7 -2
- package/dist/javascript/recovery/WakaruExecution.js +5 -2
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/main/shutdown.js +11 -3
- package/dist/main/startup.js +9 -2
- package/dist/main/transport.js +22 -2
- package/dist/main.js +11 -18
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +48 -22
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +87 -88
- package/dist/native/LldbCallTracer.js +372 -103
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +122 -31
- package/dist/native/NativeUiHelperRuntime.js +11 -2
- package/dist/native/NativeUiObservation.js +2 -2
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
- package/dist/native/pwntools/PwntoolsDecoder.js +2 -1
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +23 -10
- package/dist/process/ExecFileOutput.js +108 -6
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/PrivateRuntimeRoot.js +10 -5
- package/dist/process/ProcessOwnership.js +204 -57
- package/dist/process/ProcessOwnershipObservation.js +60 -9
- package/dist/process/ProviderProcess.js +39 -10
- package/dist/process/capture/FilesystemSnapshot.js +50 -13
- package/dist/process/capture/ProcessCaptureError.js +15 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +235 -81
- package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
- package/dist/process/capture/ProcessHarness.js +21 -25
- package/dist/process/capture/ProcessNormalization.js +20 -2
- package/dist/process/capture/ProcessSampling.js +25 -2
- package/dist/process/capture/TerminalRenderer.js +14 -0
- package/dist/process/snapshotEnvironment.js +14 -0
- package/dist/server/EvidenceMcpServer.js +157 -0
- package/dist/server/createServer.js +61 -41
- package/dist/server/mcpClientMetadata.js +12 -5
- package/dist/server/promptCompletion.js +3 -8
- package/dist/server/registerAnalysisViewTool.js +15 -0
- package/dist/server/registerAndroidTools.js +2 -5
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +4 -5
- package/dist/server/registerApplicationTools/coverage.js +1 -2
- package/dist/server/registerApplicationTools/helpers.js +1 -4
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
- package/dist/server/registerApplicationTools/traceFeature.js +4 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +13 -10
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -5
- package/dist/server/registerBrowserScenarioTool.js +3 -6
- package/dist/server/registerBrowserTools.js +13 -18
- package/dist/server/registerBundleComparisonTool.js +5 -7
- package/dist/server/registerCloseLifecycleTool.js +9 -20
- package/dist/server/registerElectronTools.js +10 -15
- package/dist/server/registerEnhancedTools.js +36 -77
- package/dist/server/registerEvidenceTools.js +3 -6
- package/dist/server/registerEvmTools.js +2 -5
- package/dist/server/registerFirmwareTools.js +2 -5
- package/dist/server/registerFunctionComparisonTool.js +15 -12
- package/dist/server/registerInvestigationTools.js +16 -17
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -5
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -8
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -8
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -7
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -9
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -9
- package/dist/server/registerOfficialTools.js +4 -21
- package/dist/server/registerProcessComparisonTool.js +74 -48
- package/dist/server/registerRecordedCrashTools.js +2 -5
- package/dist/server/registerSessionRecordTools.js +19 -24
- package/dist/server/registerSessionStatusTool.js +19 -6
- package/dist/server/registerSessionTools.js +20 -18
- package/dist/server/registerWebModuleTool.js +2 -5
- package/dist/server/registerWebNetworkCaptureTool.js +2 -5
- package/dist/server/registerWebRuntimeTools.js +4 -9
- package/dist/server/registerWebScriptTool.js +2 -5
- package/dist/server/registerWebSourceLocationTool.js +2 -5
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +0 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +75 -51
- package/dist/server/toolResultEncoding.js +34 -0
- package/dist/windows/WindowsNativeLoader.js +1 -0
- package/dist/windows/WindowsOwnedProcess.js +60 -15
- package/dist/windows/WindowsPrivateRuntime.js +7 -8
- package/install.sh +1 -1
- package/native/windows/README.md +3 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +44 -30
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +3 -6
- package/skills/reverse-engineer-anything/SKILL.md +12 -3
- package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +20 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/config.js +0 -1
- package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
- package/dist/contracts/process/processCaptureExample.js +0 -2
- package/dist/contracts/toolOutputSchemas.js +0 -2
- package/dist/ghidra/GhidraDefaults.js +0 -2
- package/dist/main/reload.js +0 -12
- package/dist/main/state.js +0 -3
- package/dist/server/sessionToolPolicies.js +0 -2
|
@@ -104,13 +104,15 @@ const recoverBundlerModule = (source, property, accumulator) => {
|
|
|
104
104
|
const exportsValue = collectJavaScriptExports(factory);
|
|
105
105
|
const requireName = factoryRequireName(factory);
|
|
106
106
|
const asyncChunks = collectBundlerAsyncChunkKeys(factory, requireName);
|
|
107
|
-
if (typeof factory.start === "number" && typeof factory.end === "number")
|
|
108
|
-
|
|
107
|
+
if (typeof factory.start === "number" && typeof factory.end === "number") {
|
|
108
|
+
const moduleRange = {
|
|
109
109
|
start: factory.start,
|
|
110
110
|
end: factory.end,
|
|
111
111
|
key,
|
|
112
112
|
requireName,
|
|
113
|
-
}
|
|
113
|
+
};
|
|
114
|
+
accumulator.moduleRangeIndex.add(moduleRange);
|
|
115
|
+
}
|
|
114
116
|
return {
|
|
115
117
|
module: {
|
|
116
118
|
module_key: key,
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
import { sanitizeEndpointCandidate } from "../browserObservation.js";
|
|
3
|
-
import { addFindingOnce, addLocatedFinding,
|
|
4
|
-
import { STATIC_ROUTE_CALL_NAMES, argumentValue, calleeName, endpointArgument as endpointArgumentHelper, prefixedArgument,
|
|
3
|
+
import { addFindingOnce, addLocatedFinding, } from "./javascriptStaticAnalysisFindings.js";
|
|
4
|
+
import { STATIC_ROUTE_CALL_NAMES, argumentValue, calleeName, endpointArgument as endpointArgumentHelper, prefixedArgument, range, rangeForOffsets, sourceSlice, staticPath, staticPathResolutionContext, storageKind, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
|
|
5
|
+
import { semanticStaticPropertyName } from "./javascriptAstValues.js";
|
|
5
6
|
/** Inspect one call or new expression for references, endpoints, storage, and roles. */
|
|
6
7
|
export const inspectCall = (source, node, context) => {
|
|
7
8
|
const { accumulator } = context;
|
|
8
9
|
const name = calleeName(node.callee);
|
|
9
10
|
const first = stringValue(node.arguments[0]);
|
|
10
|
-
const module =
|
|
11
|
+
const module = context.accumulator.moduleRangeIndex.find(node.start);
|
|
11
12
|
const moduleRequireName = module?.requireName ?? null;
|
|
12
13
|
const requireCall = requireCallSpecifier(node, name, moduleRequireName);
|
|
13
14
|
if (requireCall !== null)
|
|
@@ -103,7 +104,8 @@ const inspectEndpointCall = (node, name, first, context) => {
|
|
|
103
104
|
value: first,
|
|
104
105
|
mechanism: `call:${name}`,
|
|
105
106
|
});
|
|
106
|
-
const
|
|
107
|
+
const receiverFact = context.openReceiverFacts?.get(node.start ?? -1);
|
|
108
|
+
const endpoint = endpointArgumentHelper(name, node.arguments, node.callee, receiverFact);
|
|
107
109
|
if (endpoint !== undefined)
|
|
108
110
|
addEndpoint(context, {
|
|
109
111
|
node,
|
|
@@ -143,7 +145,16 @@ export const inspectRoleProperty = (node, context) => {
|
|
|
143
145
|
});
|
|
144
146
|
};
|
|
145
147
|
const inspectStorageCall = (node, name, first, context) => {
|
|
146
|
-
const
|
|
148
|
+
const receiverFact = context.openReceiverFacts?.get(node.start ?? -1);
|
|
149
|
+
const storage = receiverFact === "local" ||
|
|
150
|
+
receiverFact === "local-indexed-db" ||
|
|
151
|
+
receiverFact === "local-cache-storage"
|
|
152
|
+
? undefined
|
|
153
|
+
: receiverFact === "indexed-db"
|
|
154
|
+
? "indexed-db"
|
|
155
|
+
: receiverFact === "cache-storage"
|
|
156
|
+
? "cache-storage"
|
|
157
|
+
: storageKind(name);
|
|
147
158
|
if (storage === undefined)
|
|
148
159
|
return;
|
|
149
160
|
addLocatedFinding(context, {
|
|
@@ -1,3 +1,68 @@
|
|
|
1
|
+
/** Incremental point lookup preserving insertion-order precedence for overlaps. */
|
|
2
|
+
export class JavaScriptModuleRangeIndex {
|
|
3
|
+
root = {};
|
|
4
|
+
end;
|
|
5
|
+
nextOrder = 0;
|
|
6
|
+
/** Create an empty offset index bounded by the analyzed source length. */
|
|
7
|
+
constructor(sourceLength) {
|
|
8
|
+
this.end = Math.max(1, sourceLength + 1);
|
|
9
|
+
}
|
|
10
|
+
/** Add a module range in the same discovery order used by the analysis pass. */
|
|
11
|
+
add(range) {
|
|
12
|
+
const indexed = { order: this.nextOrder, range };
|
|
13
|
+
this.nextOrder += 1;
|
|
14
|
+
const start = Math.max(0, range.start);
|
|
15
|
+
const end = Math.min(this.end, range.end + 1);
|
|
16
|
+
if (start < end)
|
|
17
|
+
this.insert(this.root, 0, this.end, start, end, indexed);
|
|
18
|
+
}
|
|
19
|
+
/** Return the first discovered inclusive range containing an offset. */
|
|
20
|
+
find(offset) {
|
|
21
|
+
if (offset === null ||
|
|
22
|
+
offset === undefined ||
|
|
23
|
+
!Number.isSafeInteger(offset) ||
|
|
24
|
+
offset < 0 ||
|
|
25
|
+
offset >= this.end)
|
|
26
|
+
return undefined;
|
|
27
|
+
let node = this.root;
|
|
28
|
+
let low = 0;
|
|
29
|
+
let high = this.end;
|
|
30
|
+
let best;
|
|
31
|
+
while (node !== undefined) {
|
|
32
|
+
if (node.best !== undefined &&
|
|
33
|
+
(best === undefined || node.best.order < best.order))
|
|
34
|
+
best = node.best;
|
|
35
|
+
if (high - low <= 1)
|
|
36
|
+
break;
|
|
37
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
38
|
+
if (offset < middle) {
|
|
39
|
+
node = node.left;
|
|
40
|
+
high = middle;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
node = node.right;
|
|
44
|
+
low = middle;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return best?.range;
|
|
48
|
+
}
|
|
49
|
+
insert(node, low, high, queryLow, queryHigh, value) {
|
|
50
|
+
if (queryLow <= low && high <= queryHigh) {
|
|
51
|
+
if (node.best === undefined || value.order < node.best.order)
|
|
52
|
+
node.best = value;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
56
|
+
if (queryLow < middle) {
|
|
57
|
+
node.left ??= {};
|
|
58
|
+
this.insert(node.left, low, middle, queryLow, queryHigh, value);
|
|
59
|
+
}
|
|
60
|
+
if (queryHigh > middle) {
|
|
61
|
+
node.right ??= {};
|
|
62
|
+
this.insert(node.right, middle, high, queryLow, queryHigh, value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
1
66
|
/** Add one module-attributable finding once per source location. */
|
|
2
67
|
export const addLocatedFinding = (context, input) => addFindingOnce(context.accumulator, `${input.key}\0${String(input.node.start)}`, () => input.collection.push({
|
|
3
68
|
offset: input.node.start ?? -1,
|
|
@@ -13,11 +78,5 @@ export const addFindingOnce = (accumulator, key, add) => {
|
|
|
13
78
|
/** Attach recovered bundle-module ownership to findings after traversal. */
|
|
14
79
|
export const finalizeLocatedFindings = (values, modules) => values.map(({ offset, value }) => ({
|
|
15
80
|
...value,
|
|
16
|
-
module_key:
|
|
81
|
+
module_key: modules.find(offset)?.key ?? null,
|
|
17
82
|
}));
|
|
18
|
-
/** Locate the recovered bundle factory containing one exact source offset. */
|
|
19
|
-
export const moduleAtOffset = (offset, modules) => {
|
|
20
|
-
if (offset === null || offset === undefined)
|
|
21
|
-
return undefined;
|
|
22
|
-
return modules.find(({ start, end }) => offset >= start && offset <= end);
|
|
23
|
-
};
|
|
@@ -2,9 +2,8 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { posix } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import * as t from "@babel/types";
|
|
5
|
-
import { semanticStaticPropertyName } from "./javascriptAstValues.js";
|
|
5
|
+
import { readExactJavaScriptLiteral, semanticStaticPropertyName, } from "./javascriptAstValues.js";
|
|
6
6
|
import { compareCodePoints } from "../canonicalOrdering.js";
|
|
7
|
-
export { propertyName, semanticStaticPropertyName, } from "./javascriptAstValues.js";
|
|
8
7
|
/** Explicit result for source text that Babel cannot parse. */
|
|
9
8
|
export const failedJavaScriptStaticAnalysis = () => ({
|
|
10
9
|
parse_status: "failed",
|
|
@@ -118,10 +117,8 @@ export const staticPathResolutionContext = (node) => isFilesystemPathExpression(
|
|
|
118
117
|
const staticPathAt = (node) => {
|
|
119
118
|
if (t.isStringLiteral(node))
|
|
120
119
|
return node.value;
|
|
121
|
-
if (t.isTemplateLiteral(node) && node.expressions.length === 0)
|
|
122
|
-
|
|
123
|
-
return value;
|
|
124
|
-
}
|
|
120
|
+
if (t.isTemplateLiteral(node) && node.expressions.length === 0)
|
|
121
|
+
return stringValue(node);
|
|
125
122
|
if (t.isBinaryExpression(node, { operator: "+" })) {
|
|
126
123
|
const left = staticPathAt(node.left);
|
|
127
124
|
const right = staticPathAt(node.right);
|
|
@@ -347,23 +344,34 @@ const BROWSING_CONTEXT_KEYWORDS = new Set([
|
|
|
347
344
|
* methods' case; extension methods such as WebDAV `PROPFIND` are
|
|
348
345
|
* conventionally uppercase tokens.
|
|
349
346
|
*/
|
|
350
|
-
const xhrOpenUrl = (name, methodNode, urlNode) => {
|
|
347
|
+
const xhrOpenUrl = (name, methodNode, urlNode, receiverFact) => {
|
|
351
348
|
const url = stringValue(urlNode);
|
|
352
349
|
if (url === undefined)
|
|
353
350
|
return undefined;
|
|
351
|
+
// A lexical fact is stronger than the receiver's spelling. In particular,
|
|
352
|
+
// browser Window and Document globals overload `open` with URL/content APIs.
|
|
353
|
+
if (receiverFact === "window")
|
|
354
|
+
return undefined;
|
|
354
355
|
const method = stringValue(methodNode);
|
|
355
356
|
// IndexedDB and Cache Storage `open` take a name and a version, so a
|
|
356
357
|
// receiver spelled as storage needs a standard HTTP method literal.
|
|
357
|
-
const storage =
|
|
358
|
+
const storage = receiverFact === "local-indexed-db" ||
|
|
359
|
+
receiverFact === "local-cache-storage" ||
|
|
360
|
+
receiverFact === "indexed-db" ||
|
|
361
|
+
receiverFact === "cache-storage" ||
|
|
362
|
+
storageKind(name) !== undefined;
|
|
358
363
|
if (method === undefined)
|
|
359
364
|
return storage ||
|
|
360
|
-
WINDOW_OPEN_CALL.test(name) ||
|
|
365
|
+
(receiverFact === undefined && WINDOW_OPEN_CALL.test(name)) ||
|
|
361
366
|
FS_OPEN_FLAGS.has(url) ||
|
|
362
367
|
BROWSING_CONTEXT_KEYWORDS.has(url.toLowerCase())
|
|
363
368
|
? undefined
|
|
364
369
|
: url;
|
|
365
370
|
return XHR_METHODS.has(method.toUpperCase()) ||
|
|
366
|
-
(!storage
|
|
371
|
+
((!storage ||
|
|
372
|
+
receiverFact === "local-indexed-db" ||
|
|
373
|
+
receiverFact === "local-cache-storage") &&
|
|
374
|
+
/^[A-Z][A-Z-]*$/u.test(method))
|
|
367
375
|
? url
|
|
368
376
|
: undefined;
|
|
369
377
|
};
|
|
@@ -396,11 +404,13 @@ const isKeyedCollectionReceiver = (callee) => {
|
|
|
396
404
|
return property === "headers" || property === "searchParams";
|
|
397
405
|
};
|
|
398
406
|
/** Select the literal URL argument for recognized network callees. */
|
|
399
|
-
export const endpointArgument = (name, args, callee) => {
|
|
407
|
+
export const endpointArgument = (name, args, callee, receiverFact) => {
|
|
408
|
+
if (receiverFact === "window")
|
|
409
|
+
return undefined;
|
|
400
410
|
if (name === "fetch" || name.endsWith(".fetch") || name === "WebSocket")
|
|
401
411
|
return stringValue(args[0]);
|
|
402
412
|
if (name.endsWith(".open"))
|
|
403
|
-
return xhrOpenUrl(name, args[0], args[1]);
|
|
413
|
+
return xhrOpenUrl(name, args[0], args[1], receiverFact);
|
|
404
414
|
const method = ["get", "post", "put", "patch", "delete", "request"].find((candidate) => name === candidate || name.endsWith(`.${candidate}`));
|
|
405
415
|
if (method !== undefined) {
|
|
406
416
|
const value = stringValue(args[0]);
|
|
@@ -462,11 +472,12 @@ const memberPropertyName = (node) => node.computed &&
|
|
|
462
472
|
* literal without substitutions denotes the same exact string.
|
|
463
473
|
*/
|
|
464
474
|
export const stringValue = (node) => {
|
|
465
|
-
if (
|
|
466
|
-
return
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
475
|
+
if (node === null || node === undefined)
|
|
476
|
+
return undefined;
|
|
477
|
+
const literal = readExactJavaScriptLiteral(node);
|
|
478
|
+
return literal.found && typeof literal.value === "string"
|
|
479
|
+
? literal.value
|
|
480
|
+
: undefined;
|
|
470
481
|
};
|
|
471
482
|
/** Return a string or numeric argument literal. */
|
|
472
483
|
export const argumentValue = (node) => t.isNumericLiteral(node) ? String(node.value) : stringValue(node);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { JavaScriptModuleRangeIndex } from "./javascriptStaticAnalysisFindings.js";
|
|
1
2
|
/** Create isolated mutable state for one source analysis. */
|
|
2
|
-
export const createJavaScriptAnalysisAccumulator = () => ({
|
|
3
|
+
export const createJavaScriptAnalysisAccumulator = (sourceLength) => ({
|
|
3
4
|
references: [],
|
|
4
5
|
endpoints: [],
|
|
5
6
|
storage: [],
|
|
@@ -12,7 +13,7 @@ export const createJavaScriptAnalysisAccumulator = () => ({
|
|
|
12
13
|
senderValidations: [],
|
|
13
14
|
utilityProcesses: [],
|
|
14
15
|
nativeAddonBindings: [],
|
|
15
|
-
|
|
16
|
+
moduleRangeIndex: new JavaScriptModuleRangeIndex(sourceLength),
|
|
16
17
|
seen: new Set(),
|
|
17
18
|
visitedNodes: 0,
|
|
18
19
|
unknownFindings: 0,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { compareCodePoints, uniqueSorted } from "../canonicalOrdering.js";
|
|
2
2
|
import { absenceClaimable, canonicalDigest } from "../comparisonSemantics.js";
|
|
3
3
|
import { SOURCE_TO_BUNDLE_SIGNAL_WEIGHTS, sourceToBundleComparisonResultSchema, } from "./sourceToBundleComparisonSchemas.js";
|
|
4
|
-
import { buildSourceToBundleCandidateIndex, candidateIdsForSource, historicalSourceFiles, scoreSourceToBundleCandidate, sourceBearingNodes, } from "./sourceToBundleSignals.js";
|
|
4
|
+
import { buildSourceToBundleCandidateIndex, candidateHasDigest, candidateIdsForSource, historicalSourceFiles, scoreSourceToBundleCandidate, sourceBearingNodes, } from "./sourceToBundleSignals.js";
|
|
5
5
|
/** Compare historical source files to static source-bearing application nodes. */
|
|
6
6
|
export const compareSourceToBundle = (input) => {
|
|
7
7
|
const projection = projectComparison(input);
|
|
@@ -63,7 +63,7 @@ const compareMappings = (input, projection) => {
|
|
|
63
63
|
.map((nodeId) => scoreSourceToBundleCandidate(source, nodeId, projection.index))
|
|
64
64
|
.filter((candidate) => candidate !== null)
|
|
65
65
|
.sort(compareCandidates);
|
|
66
|
-
const classification = classifyMapping(scored, projection.absenceComplete);
|
|
66
|
+
const classification = classifyMapping(scored, projection.absenceComplete, (nodeId) => source.sha256 !== null && candidateHasDigest(projection.index, nodeId));
|
|
67
67
|
const semantic = {
|
|
68
68
|
source_path: source.path,
|
|
69
69
|
source_sha256: source.sha256,
|
|
@@ -103,7 +103,7 @@ const scoringModel = () => ({
|
|
|
103
103
|
weight,
|
|
104
104
|
})),
|
|
105
105
|
});
|
|
106
|
-
const classifyMapping = (candidates, absenceComplete) => {
|
|
106
|
+
const classifyMapping = (candidates, absenceComplete, digestComparable) => {
|
|
107
107
|
const exact = candidates.filter((candidate) => hasSignal(candidate, "exact-source-digest"));
|
|
108
108
|
if (exact.length === 1)
|
|
109
109
|
return {
|
|
@@ -134,6 +134,15 @@ const classifyMapping = (candidates, absenceComplete) => {
|
|
|
134
134
|
: pathCandidates.filter(({ score }) => score === topScore);
|
|
135
135
|
if (topPathCandidates.length === 1) {
|
|
136
136
|
const candidate = topPathCandidates[0];
|
|
137
|
+
if (candidate !== undefined && digestComparable(candidate.current_node_id))
|
|
138
|
+
return {
|
|
139
|
+
status: "modified",
|
|
140
|
+
confidence: candidate.confidence === "high" ? "high" : "medium",
|
|
141
|
+
currentNodeIds: [candidate.current_node_id],
|
|
142
|
+
limitations: [
|
|
143
|
+
"Location evidence links the source to the current node, but their source digests differ.",
|
|
144
|
+
],
|
|
145
|
+
};
|
|
137
146
|
return {
|
|
138
147
|
status: "unknown",
|
|
139
148
|
confidence: "unknown",
|
|
@@ -39,7 +39,9 @@ export const buildSourceToBundleCandidateIndex = (nodes) => {
|
|
|
39
39
|
for (const digest of projection.digests)
|
|
40
40
|
addIndexValue(byDigest, digest, projection.node.node_id);
|
|
41
41
|
for (const path of projection.paths) {
|
|
42
|
-
for (const suffix of
|
|
42
|
+
for (const suffix of path.allowSuffix
|
|
43
|
+
? pathSuffixes(path.value)
|
|
44
|
+
: [path.value])
|
|
43
45
|
addIndexValue(byPathSuffix, suffix, projection.node.node_id);
|
|
44
46
|
addIndexValue(byBasename, posix.basename(path.value), projection.node.node_id);
|
|
45
47
|
}
|
|
@@ -72,6 +74,8 @@ export const candidateIdsForSource = (source, index) => {
|
|
|
72
74
|
}
|
|
73
75
|
return output;
|
|
74
76
|
};
|
|
77
|
+
/** Whether an indexed candidate carries any content digest to compare. */
|
|
78
|
+
export const candidateHasDigest = (index, nodeId) => (index.nodes.get(nodeId)?.digests.size ?? 0) > 0;
|
|
75
79
|
/** Score one indexed candidate from explicit, caller-visible signals. */
|
|
76
80
|
export const scoreSourceToBundleCandidate = (source, nodeId, index) => {
|
|
77
81
|
const projection = index.nodes.get(nodeId);
|
|
@@ -97,16 +101,26 @@ const projectCurrentNode = (node) => {
|
|
|
97
101
|
if (node.identity.strategy === "source-map-original") {
|
|
98
102
|
if (node.identity.source_sha256 !== null)
|
|
99
103
|
digests.add(node.identity.source_sha256);
|
|
100
|
-
addPath(paths, "source-map-original", node.identity.original_source);
|
|
101
104
|
}
|
|
102
105
|
if (node.identity.strategy === "canonical-path")
|
|
103
106
|
addPath(paths, "canonical-path", node.identity.path);
|
|
104
107
|
for (const observation of node.observations) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
if (node.identity.strategy === "source-map-original") {
|
|
109
|
+
const resolution = observation.source_map_reference?.resolution;
|
|
110
|
+
if (resolution !== undefined && resolution.kind !== "unresolved")
|
|
111
|
+
paths.push({
|
|
112
|
+
kind: "source-map-original",
|
|
113
|
+
value: resolution.path,
|
|
114
|
+
allowSuffix: resolution.kind === "suffix",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const sourceDigest = observation.properties.source_sha256;
|
|
119
|
+
if (typeof sourceDigest === "string" && isDigest(sourceDigest))
|
|
120
|
+
digests.add(sourceDigest);
|
|
121
|
+
for (const key of PATH_PROPERTIES)
|
|
122
|
+
addJsonPath(paths, observation.properties[key]);
|
|
123
|
+
}
|
|
110
124
|
}
|
|
111
125
|
return {
|
|
112
126
|
node,
|
|
@@ -128,7 +142,9 @@ const candidateSignals = (source, current) => {
|
|
|
128
142
|
if (exactPaths.length > 0)
|
|
129
143
|
signals.push(signal("current-path-exact", source.path, exactPaths));
|
|
130
144
|
const suffixPaths = otherPaths
|
|
131
|
-
.filter(({ value }) =>
|
|
145
|
+
.filter(({ value, allowSuffix }) => allowSuffix &&
|
|
146
|
+
value !== source.path &&
|
|
147
|
+
value.endsWith(`/${source.path}`))
|
|
132
148
|
.map(({ value }) => value);
|
|
133
149
|
if (suffixPaths.length > 0)
|
|
134
150
|
signals.push(signal("current-path-suffix", source.path, suffixPaths));
|
|
@@ -161,7 +177,8 @@ const candidateConfidence = (signals) => {
|
|
|
161
177
|
return kinds.has("current-path-suffix") ? "medium" : "low";
|
|
162
178
|
};
|
|
163
179
|
const matchingPaths = (sourcePath, currentPaths) => currentPaths
|
|
164
|
-
.filter(({ value }) => value === sourcePath ||
|
|
180
|
+
.filter(({ value, allowSuffix }) => value === sourcePath ||
|
|
181
|
+
(allowSuffix && value.endsWith(`/${sourcePath}`)))
|
|
165
182
|
.map(({ value }) => value);
|
|
166
183
|
const addJsonPath = (paths, value) => {
|
|
167
184
|
if (typeof value === "string")
|
|
@@ -170,27 +187,38 @@ const addJsonPath = (paths, value) => {
|
|
|
170
187
|
const addPath = (paths, kind, raw) => {
|
|
171
188
|
const value = normalizeCurrentPath(raw);
|
|
172
189
|
if (value !== null)
|
|
173
|
-
paths.push({ kind, value });
|
|
190
|
+
paths.push({ kind, value, allowSuffix: true });
|
|
174
191
|
};
|
|
175
|
-
/** Matches a `scheme://...` URL prefix; bare filesystem paths keep `?`/`#`. */
|
|
176
192
|
const SCHEME_URL = /^[a-z][a-z0-9+.-]*:\/\//iu;
|
|
177
|
-
/** Matches a `scheme://...` URL prefix with any run of slashes, for stripping. */
|
|
178
193
|
const SCHEME_URL_PREFIX = /^[a-z][a-z0-9+.-]*:\/\/+/iu;
|
|
179
194
|
const normalizeCurrentPath = (raw) => {
|
|
180
195
|
const withoutQuery = SCHEME_URL.test(raw)
|
|
181
196
|
? (raw.split(/[?#]/u, 1)[0] ?? "")
|
|
182
197
|
: raw;
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
.replaceAll("\\", "/")
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
const portable = withoutQuery
|
|
199
|
+
.replace(SCHEME_URL_PREFIX, "")
|
|
200
|
+
.replaceAll("\\", "/");
|
|
201
|
+
const parts = [];
|
|
202
|
+
for (const part of portable.split("/")) {
|
|
203
|
+
if (part === "" || part === ".")
|
|
204
|
+
continue;
|
|
205
|
+
if (part === "..") {
|
|
206
|
+
if (parts.length === 0)
|
|
207
|
+
return null;
|
|
208
|
+
parts.pop();
|
|
209
|
+
}
|
|
210
|
+
else
|
|
211
|
+
parts.push(part);
|
|
212
|
+
}
|
|
213
|
+
if (parts.length === 0)
|
|
189
214
|
return null;
|
|
190
215
|
return parts.join("/");
|
|
191
216
|
};
|
|
192
217
|
const uniquePaths = (paths) => [
|
|
193
|
-
...new Map(paths.map((path) => [
|
|
218
|
+
...new Map(paths.map((path) => [
|
|
219
|
+
`${path.kind}\0${path.value}\0${String(path.allowSuffix)}`,
|
|
220
|
+
path,
|
|
221
|
+
])).values(),
|
|
194
222
|
].sort((left, right) => compareCodePoints(`${left.kind}\0${left.value}`, `${right.kind}\0${right.value}`));
|
|
195
223
|
const pathSuffixes = (path) => {
|
|
196
224
|
const parts = path.split("/");
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** Encode ordinary JSON as bounded string parts without a document-sized allocation. */
|
|
2
|
+
export function* jsonParts(value, pretty = false) {
|
|
3
|
+
yield* encodeValue(value, pretty, 0, new Set(), false);
|
|
4
|
+
}
|
|
5
|
+
/** Encode validated JSON with canonical key ordering without allocating the whole document. */
|
|
6
|
+
export function* canonicalJsonParts(value) {
|
|
7
|
+
yield* encodeValue(value, false, 0, new Set(), true);
|
|
8
|
+
}
|
|
9
|
+
/** Buffer JSON parts while preserving complete UTF-16 surrogate pairs. */
|
|
10
|
+
export function* bufferedJsonParts(parts) {
|
|
11
|
+
let buffer = "";
|
|
12
|
+
for (const part of parts) {
|
|
13
|
+
if (buffer.length + part.length > 64 * 1024 && buffer !== "") {
|
|
14
|
+
yield buffer;
|
|
15
|
+
buffer = "";
|
|
16
|
+
}
|
|
17
|
+
buffer += part;
|
|
18
|
+
}
|
|
19
|
+
if (buffer !== "")
|
|
20
|
+
yield buffer;
|
|
21
|
+
}
|
|
22
|
+
function* encodeString(value) {
|
|
23
|
+
if (value.length <= 8192) {
|
|
24
|
+
yield JSON.stringify(value);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
yield '"';
|
|
28
|
+
for (let start = 0; start < value.length;) {
|
|
29
|
+
let end = Math.min(start + 8192, value.length);
|
|
30
|
+
const last = value.charCodeAt(end - 1);
|
|
31
|
+
const next = value.charCodeAt(end);
|
|
32
|
+
// Keep a surrogate pair in the same JSON.stringify and UTF-8 write.
|
|
33
|
+
if (end < value.length &&
|
|
34
|
+
last >= 0xd800 &&
|
|
35
|
+
last <= 0xdbff &&
|
|
36
|
+
next >= 0xdc00 &&
|
|
37
|
+
next <= 0xdfff)
|
|
38
|
+
end -= 1;
|
|
39
|
+
yield JSON.stringify(value.slice(start, end)).slice(1, -1);
|
|
40
|
+
start = end;
|
|
41
|
+
}
|
|
42
|
+
yield '"';
|
|
43
|
+
}
|
|
44
|
+
function* encodeValue(value, pretty, depth, ancestors, canonical) {
|
|
45
|
+
if (typeof value === "string") {
|
|
46
|
+
yield* encodeString(value);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (value === null || typeof value === "boolean") {
|
|
50
|
+
yield value === null ? "null" : String(value);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
54
|
+
yield String(value);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (typeof value !== "object" || value === null)
|
|
58
|
+
throw new TypeError("JSON output requires ordinary JSON values");
|
|
59
|
+
if (ancestors.has(value))
|
|
60
|
+
throw new TypeError("JSON output contains a circular reference");
|
|
61
|
+
if (!Array.isArray(value) &&
|
|
62
|
+
Object.prototype.toString.call(value) !== "[object Object]")
|
|
63
|
+
throw new TypeError("JSON output requires ordinary JSON objects");
|
|
64
|
+
ancestors.add(value);
|
|
65
|
+
try {
|
|
66
|
+
const array = Array.isArray(value);
|
|
67
|
+
const keys = array ? undefined : Object.keys(value);
|
|
68
|
+
if (canonical)
|
|
69
|
+
keys?.sort();
|
|
70
|
+
const count = array ? value.length : (keys?.length ?? 0);
|
|
71
|
+
let written = 0;
|
|
72
|
+
yield array ? "[" : "{";
|
|
73
|
+
for (let index = 0; index < count; index += 1) {
|
|
74
|
+
let item;
|
|
75
|
+
let key;
|
|
76
|
+
if (array) {
|
|
77
|
+
item = value[index];
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
key = keys?.[index];
|
|
81
|
+
if (key === undefined)
|
|
82
|
+
throw new TypeError("JSON object changed during serialization");
|
|
83
|
+
item = Reflect.get(value, key);
|
|
84
|
+
// Incur's filter can select inherited methods. Match native JSON's
|
|
85
|
+
// omission without eagerly reading the rest of a bounded result.
|
|
86
|
+
if (item === undefined ||
|
|
87
|
+
typeof item === "function" ||
|
|
88
|
+
typeof item === "symbol")
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (written > 0)
|
|
92
|
+
yield ",";
|
|
93
|
+
if (pretty)
|
|
94
|
+
yield `\n${" ".repeat(depth + 1)}`;
|
|
95
|
+
if (key !== undefined) {
|
|
96
|
+
yield* encodeString(key);
|
|
97
|
+
yield pretty ? ": " : ":";
|
|
98
|
+
}
|
|
99
|
+
yield* encodeValue(item, pretty, depth + 1, ancestors, canonical);
|
|
100
|
+
written += 1;
|
|
101
|
+
}
|
|
102
|
+
if (pretty && written > 0)
|
|
103
|
+
yield `\n${" ".repeat(depth)}`;
|
|
104
|
+
yield array ? "]" : "}";
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
ancestors.delete(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
package/dist/domain/jsonValue.js
CHANGED
|
@@ -1,9 +1,93 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { isImmutableJsonSnapshot } from "./immutableJson.js";
|
|
3
|
+
/** Maximum JSON nesting accepted before recursive result cloning. */
|
|
4
|
+
export const MAX_JSON_DEPTH = 1000;
|
|
5
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
const recordShape = z.record(z.string(), z.unknown());
|
|
7
|
+
const immutableValidation = new WeakMap();
|
|
8
|
+
/** Validate JSON meaning and nesting without cloning a trusted immutable value. */
|
|
9
|
+
export const jsonValueValidationIssue = (root) => {
|
|
10
|
+
const steps = jsonValueValidationSteps(root);
|
|
11
|
+
for (;;) {
|
|
12
|
+
const step = steps.next();
|
|
13
|
+
if (step.done)
|
|
14
|
+
return step.value;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/** Validate JSON in bounded steps; cache only authenticated immutable roots. */
|
|
18
|
+
export function* jsonValueValidationSteps(root) {
|
|
19
|
+
const immutable = typeof root === "object" && root !== null && isImmutableJsonSnapshot(root)
|
|
20
|
+
? root
|
|
21
|
+
: undefined;
|
|
22
|
+
if (immutable !== undefined && immutableValidation.has(immutable))
|
|
23
|
+
return immutableValidation.get(immutable);
|
|
24
|
+
const finish = (issue) => {
|
|
25
|
+
if (immutable !== undefined)
|
|
26
|
+
immutableValidation.set(immutable, issue);
|
|
27
|
+
return issue;
|
|
28
|
+
};
|
|
29
|
+
const pending = [
|
|
30
|
+
{ value: root, depth: 0 },
|
|
31
|
+
];
|
|
32
|
+
let examined = 0;
|
|
33
|
+
while (pending.length > 0) {
|
|
34
|
+
if (examined++ === 4096) {
|
|
35
|
+
examined = 0;
|
|
36
|
+
yield;
|
|
37
|
+
}
|
|
38
|
+
const item = pending.pop();
|
|
39
|
+
if (item === undefined)
|
|
40
|
+
break;
|
|
41
|
+
if (item.depth > MAX_JSON_DEPTH)
|
|
42
|
+
return finish(`JSON value exceeds maximum nesting depth of ${MAX_JSON_DEPTH}`);
|
|
43
|
+
const value = item.value;
|
|
44
|
+
if (value === null ||
|
|
45
|
+
typeof value === "string" ||
|
|
46
|
+
typeof value === "boolean")
|
|
47
|
+
continue;
|
|
48
|
+
if (typeof value === "number") {
|
|
49
|
+
if (!Number.isFinite(value))
|
|
50
|
+
return finish("JSON numbers must be finite");
|
|
51
|
+
}
|
|
52
|
+
else if (Array.isArray(value)) {
|
|
53
|
+
for (const child of value)
|
|
54
|
+
pending.push({ value: child, depth: item.depth + 1 });
|
|
55
|
+
}
|
|
56
|
+
else if (isRecord(value) && recordShape.safeParse(value).success) {
|
|
57
|
+
// Inspect every own member, including keys Zod's record parser skips.
|
|
58
|
+
for (const child of Object.values(value))
|
|
59
|
+
pending.push({ value: child, depth: item.depth + 1 });
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
return finish("Invalid JSON value");
|
|
63
|
+
}
|
|
64
|
+
return finish(undefined);
|
|
65
|
+
}
|
|
66
|
+
const preserveJsonValue = (value) => {
|
|
67
|
+
if (Array.isArray(value))
|
|
68
|
+
return value.map(preserveJsonValue);
|
|
69
|
+
if (value !== null && typeof value === "object")
|
|
70
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [
|
|
71
|
+
key,
|
|
72
|
+
preserveJsonValue(child),
|
|
73
|
+
]));
|
|
74
|
+
return value;
|
|
75
|
+
};
|
|
76
|
+
const validatedJsonValue = z.custom((value) => jsonValueValidationIssue(value) === undefined, {
|
|
77
|
+
error: (issue) => jsonValueValidationIssue(issue.input) ?? "Invalid JSON value",
|
|
78
|
+
});
|
|
79
|
+
// Keep both stages nonrecursive in public and Standard Schema projections.
|
|
80
|
+
validatedJsonValue._zod.toJSONSchema = () => ({});
|
|
81
|
+
/** Parse bounded JSON and retain all own data members without prototype setters. */
|
|
82
|
+
export const jsonValueSchema = z
|
|
83
|
+
.unknown()
|
|
84
|
+
.nonoptional()
|
|
85
|
+
.pipe(validatedJsonValue)
|
|
86
|
+
.transform(preserveJsonValue);
|
|
7
87
|
jsonValueSchema._zod.toJSONSchema = () => ({});
|
|
88
|
+
const objectValidation = z.custom(isRecord, "Expected JSON object");
|
|
89
|
+
const objectProjection = () => ({ type: "object", additionalProperties: {} });
|
|
90
|
+
objectValidation._zod.toJSONSchema = objectProjection;
|
|
8
91
|
/** JSON object boundary for caller-visible parameter maps. */
|
|
9
|
-
export const jsonObjectSchema =
|
|
92
|
+
export const jsonObjectSchema = jsonValueSchema.pipe(objectValidation);
|
|
93
|
+
jsonObjectSchema._zod.toJSONSchema = objectProjection;
|
package/dist/domain/localPath.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { isAbsolute, relative, sep } from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/** Preserve selected filesystem names while rejecting OS-invalid NUL bytes. */
|
|
4
|
+
export const localPathStringSchema = z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1)
|
|
7
|
+
.regex(/^[^\u0000]*$/u, "Local filesystem paths cannot contain NUL");
|
|
2
8
|
/** True when the value is an absolute filesystem path on the host platform. */
|
|
3
9
|
export const isAbsoluteLocalPath = (value) => isAbsolute(value);
|
|
4
10
|
/** Test lexical containment on the host platform; callers must resolve symlinks first. */
|