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,20 +1,54 @@
|
|
|
1
|
-
import { open } from "node:fs/promises";
|
|
2
1
|
import { PassThrough } from "node:stream";
|
|
3
2
|
import { once } from "node:events";
|
|
4
3
|
import { Reader, ZipReader } from "@zip.js/zip.js";
|
|
5
|
-
import { ArtifactReaderFailure, } from "./ArtifactReader.js";
|
|
4
|
+
import { ArtifactReaderFailure, copyArtifactEntry, sameArtifactEntry, } from "./ArtifactReader.js";
|
|
5
|
+
import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js";
|
|
6
|
+
import { NonRegularFileReadError, RegularFileAdmissionFailure, openRegularFile, sameRegularFileState, } from "../filesystem/RegularFile.js";
|
|
6
7
|
class NodeFileReader extends Reader {
|
|
7
8
|
path;
|
|
8
9
|
maximumReadBytes;
|
|
10
|
+
admitted;
|
|
9
11
|
#handle;
|
|
10
|
-
|
|
12
|
+
#owner;
|
|
13
|
+
#initPromise;
|
|
14
|
+
#ownsHandle;
|
|
15
|
+
constructor(path, maximumReadBytes, admitted) {
|
|
11
16
|
super(path);
|
|
12
17
|
this.path = path;
|
|
13
18
|
this.maximumReadBytes = maximumReadBytes;
|
|
19
|
+
this.admitted = admitted;
|
|
20
|
+
this.#ownsHandle = admitted === undefined;
|
|
14
21
|
}
|
|
15
|
-
|
|
16
|
-
this.#
|
|
17
|
-
|
|
22
|
+
init() {
|
|
23
|
+
this.#initPromise ??= this.#initialize();
|
|
24
|
+
return this.#initPromise;
|
|
25
|
+
}
|
|
26
|
+
async #initialize() {
|
|
27
|
+
try {
|
|
28
|
+
const handle = this.admitted?.handle ??
|
|
29
|
+
(await openRegularFile(this.path, { symlinks: "reject" }));
|
|
30
|
+
this.#handle = handle;
|
|
31
|
+
if (this.#ownsHandle)
|
|
32
|
+
this.#owner = new OwnedFileHandle(handle);
|
|
33
|
+
}
|
|
34
|
+
catch (cause) {
|
|
35
|
+
if (cause instanceof RegularFileAdmissionFailure) {
|
|
36
|
+
this.#owner = cause.owner;
|
|
37
|
+
const primary = cause.cause instanceof NonRegularFileReadError
|
|
38
|
+
? new ArtifactReaderFailure("format", `ZIP source is not a regular file: ${this.path}`, { cause: cause.cause })
|
|
39
|
+
: cause.cause;
|
|
40
|
+
throw ArtifactReaderFailure.withCleanup(primary, ArtifactReaderFailure.cleanupObservation(cause.cleanupCause, this.path));
|
|
41
|
+
}
|
|
42
|
+
if (cause instanceof NonRegularFileReadError)
|
|
43
|
+
throw new ArtifactReaderFailure("format", `ZIP source is not a regular file: ${this.path}`, { cause });
|
|
44
|
+
throw cause;
|
|
45
|
+
}
|
|
46
|
+
const metadata = await this.#handle.stat();
|
|
47
|
+
if (!metadata.isFile() ||
|
|
48
|
+
(this.admitted !== undefined &&
|
|
49
|
+
!sameRegularFileState(this.admitted.initial, metadata)))
|
|
50
|
+
throw new ArtifactReaderFailure("integrity", `ZIP source identity changed before reading: ${this.path}`);
|
|
51
|
+
this.size = metadata.size;
|
|
18
52
|
}
|
|
19
53
|
async readUint8Array(index, length) {
|
|
20
54
|
const handle = this.#handle;
|
|
@@ -29,7 +63,13 @@ class NodeFileReader extends Reader {
|
|
|
29
63
|
return bytes.subarray(0, read.bytesRead);
|
|
30
64
|
}
|
|
31
65
|
async closeHandle() {
|
|
32
|
-
|
|
66
|
+
if (!this.#ownsHandle)
|
|
67
|
+
return;
|
|
68
|
+
await this.#initPromise?.catch(() => undefined);
|
|
69
|
+
if (this.#owner === undefined)
|
|
70
|
+
return;
|
|
71
|
+
await this.#owner.close();
|
|
72
|
+
this.#owner = undefined;
|
|
33
73
|
this.#handle = undefined;
|
|
34
74
|
}
|
|
35
75
|
}
|
|
@@ -40,9 +80,9 @@ export class ZipArtifactReader {
|
|
|
40
80
|
#reader;
|
|
41
81
|
#entries = new Map();
|
|
42
82
|
/** Optionally bound each metadata read before allocating its backing buffer. */
|
|
43
|
-
constructor(path, format, maximumMetadataReadBytes) {
|
|
83
|
+
constructor(path, format, maximumMetadataReadBytes, admitted) {
|
|
44
84
|
this.format = format;
|
|
45
|
-
this.#source = new NodeFileReader(path, maximumMetadataReadBytes);
|
|
85
|
+
this.#source = new NodeFileReader(path, maximumMetadataReadBytes, admitted);
|
|
46
86
|
this.#reader = new ZipReader(this.#source, {
|
|
47
87
|
checkSignature: true,
|
|
48
88
|
checkOverlappingEntry: true,
|
|
@@ -54,31 +94,25 @@ export class ZipArtifactReader {
|
|
|
54
94
|
async *entries(signal) {
|
|
55
95
|
for await (const entry of this.#reader.getEntriesGenerator()) {
|
|
56
96
|
abortIfNeeded(signal);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
compressedSize: entry.directory ? null : entry.compressedSize,
|
|
64
|
-
executable: entry.executable,
|
|
65
|
-
encrypted: entry.encrypted,
|
|
66
|
-
byteOffset: null,
|
|
67
|
-
declaredSha256: null,
|
|
68
|
-
unpacked: false,
|
|
69
|
-
limitations: symlink ? ["Archive symlink target was not read."] : [],
|
|
70
|
-
adapterKey: entry.filename,
|
|
71
|
-
};
|
|
97
|
+
const metadata = projectZipEntry(entry);
|
|
98
|
+
this.#entries.set(entry.filename, {
|
|
99
|
+
source: entry,
|
|
100
|
+
metadata: copyArtifactEntry(metadata),
|
|
101
|
+
});
|
|
102
|
+
yield metadata;
|
|
72
103
|
}
|
|
73
104
|
}
|
|
74
105
|
open(entry, signal) {
|
|
75
106
|
abortIfNeeded(signal);
|
|
76
107
|
const stored = this.#entries.get(entry.adapterKey);
|
|
77
|
-
if (stored === undefined || stored.
|
|
108
|
+
if (stored === undefined || !sameArtifactEntry(entry, stored.metadata))
|
|
109
|
+
return Promise.reject(new ArtifactReaderFailure("integrity", "ZIP entry metadata does not match this reader's inventory"));
|
|
110
|
+
const source = stored.source;
|
|
111
|
+
if (source.directory || isSymlink(source))
|
|
78
112
|
return Promise.reject(new ArtifactReaderFailure("format", "ZIP entry is not a regular file"));
|
|
79
|
-
if (
|
|
113
|
+
if (source.encrypted)
|
|
80
114
|
return Promise.reject(new ArtifactReaderFailure("unavailable", "Encrypted ZIP entry is unsupported"));
|
|
81
|
-
return Promise.resolve(extractStream(
|
|
115
|
+
return Promise.resolve(extractStream(source, signal));
|
|
82
116
|
}
|
|
83
117
|
async close() {
|
|
84
118
|
// best-effort cleanup: zip-reader close must not mask prior extraction state.
|
|
@@ -89,6 +123,22 @@ export class ZipArtifactReader {
|
|
|
89
123
|
return [];
|
|
90
124
|
}
|
|
91
125
|
}
|
|
126
|
+
const projectZipEntry = (entry) => {
|
|
127
|
+
const symlink = isSymlink(entry);
|
|
128
|
+
return {
|
|
129
|
+
path: entry.filename,
|
|
130
|
+
kind: entry.directory ? "directory" : symlink ? "symlink" : "file",
|
|
131
|
+
declaredSize: entry.directory ? null : entry.uncompressedSize,
|
|
132
|
+
compressedSize: entry.directory ? null : entry.compressedSize,
|
|
133
|
+
executable: entry.executable,
|
|
134
|
+
encrypted: entry.encrypted,
|
|
135
|
+
byteOffset: null,
|
|
136
|
+
declaredSha256: null,
|
|
137
|
+
unpacked: false,
|
|
138
|
+
limitations: symlink ? ["Archive symlink target was not read."] : [],
|
|
139
|
+
adapterKey: entry.filename,
|
|
140
|
+
};
|
|
141
|
+
};
|
|
92
142
|
const extractStream = (entry, signal) => {
|
|
93
143
|
const output = new PassThrough();
|
|
94
144
|
const controller = new AbortController();
|
|
@@ -4,10 +4,11 @@ import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
|
|
|
4
4
|
import { projectPlistValue } from "../../domain/apple/plistValue.js";
|
|
5
5
|
import { omittedPrototypeKeysLimitation, parseXmlPropertyList, } from "../../domain/propertyListKeys.js";
|
|
6
6
|
import { decodeNibArchive } from "./NibArchive.js";
|
|
7
|
-
import {
|
|
7
|
+
import { preflightPropertyListDecode, InterfaceBuilderDecodeBudget, InterfaceBuilderDecodeBudgetExceeded, } from "./InterfaceBuilderDecodeBudget.js";
|
|
8
8
|
import { buildInterfaceBuilderAnalysis, interfaceBuilderLimitsSchema, } from "../../domain/apple/interfaceBuilderGraph.js";
|
|
9
9
|
import { mergeNibHierarchies, projectNibViewHierarchy, } from "./NibViewHierarchy.js";
|
|
10
10
|
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
|
11
|
+
import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
|
|
11
12
|
import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
|
|
12
13
|
const MAX_AGGREGATE_INPUT_BYTES = 32 * 1024 * 1024;
|
|
13
14
|
const MAX_AGGREGATE_DECODE_BYTES = 256 * 1024 * 1024;
|
|
@@ -24,7 +25,6 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
24
25
|
const prototypeKeyOmissions = new Map();
|
|
25
26
|
let omitted = 0;
|
|
26
27
|
let attempted = 0;
|
|
27
|
-
let candidates = 0;
|
|
28
28
|
let aggregateInputBytes = 0;
|
|
29
29
|
const decodeBudget = new InterfaceBuilderDecodeBudget(MAX_AGGREGATE_DECODE_BYTES);
|
|
30
30
|
const recordOmittedArchive = (path, reason) => {
|
|
@@ -34,15 +34,12 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
34
34
|
unreportedOmittedArchives += 1;
|
|
35
35
|
};
|
|
36
36
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
recordOmittedArchive(entry.path, "max_documents");
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
37
|
+
const selection = await selectInterfaceBuilderCandidates(reader, input.signal, limits.max_documents);
|
|
38
|
+
omitted = selection.omitted;
|
|
39
|
+
for (const entry of selection.omittedSamples)
|
|
40
|
+
recordOmittedArchive(entry.path, "max_documents");
|
|
41
|
+
unreportedOmittedArchives += selection.unreportedOmitted;
|
|
42
|
+
for (const entry of selection.selected) {
|
|
46
43
|
try {
|
|
47
44
|
const remainingInputBytes = MAX_AGGREGATE_INPUT_BYTES - aggregateInputBytes;
|
|
48
45
|
if (entry.declaredSize !== null &&
|
|
@@ -57,6 +54,7 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
57
54
|
const isNibArchive = bytes.subarray(0, 10).toString("ascii") === "NIBArchive";
|
|
58
55
|
let nib = null;
|
|
59
56
|
let xmlText;
|
|
57
|
+
let binaryPrototypeKeyObserved = false;
|
|
60
58
|
if (isNibArchive) {
|
|
61
59
|
const documentBudget = new InterfaceBuilderDecodeBudget(decodeBudget.remainingBytes);
|
|
62
60
|
nib = projectNibArchive(decodeNibArchive(bytes, documentBudget), documentBudget, limits.max_objects);
|
|
@@ -65,15 +63,17 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
65
63
|
else {
|
|
66
64
|
if (bytes.subarray(0, 8).toString("ascii") !== "bplist00")
|
|
67
65
|
xmlText = decodeXmlPlistText(bytes);
|
|
68
|
-
const decodedReservation =
|
|
69
|
-
decodeBudget.reserve(decodedReservation, "plist representation exceeds the aggregate Interface Builder decode budget");
|
|
66
|
+
const decodedReservation = preflightPropertyListDecode(bytes, decodeBudget.remainingBytes, xmlText);
|
|
67
|
+
decodeBudget.reserve(decodedReservation.estimatedBytes, "plist representation exceeds the aggregate Interface Builder decode budget");
|
|
68
|
+
binaryPrototypeKeyObserved =
|
|
69
|
+
decodedReservation.binaryPrototypeKeyObserved;
|
|
70
70
|
}
|
|
71
71
|
const { value: raw, omittedPrototypeKeys } = nib === null
|
|
72
|
-
? decodePlist(bytes, xmlText)
|
|
72
|
+
? decodePlist(bytes, xmlText, binaryPrototypeKeyObserved)
|
|
73
73
|
: { value: nib.raw, omittedPrototypeKeys: 0 };
|
|
74
74
|
if (nib !== null && nib.omitted > 0)
|
|
75
75
|
incompleteHierarchies.set(entry.path, nib.omitted);
|
|
76
|
-
if (omittedPrototypeKeys
|
|
76
|
+
if (omittedPrototypeKeys !== 0)
|
|
77
77
|
prototypeKeyOmissions.set(entry.path, omittedPrototypeKeys);
|
|
78
78
|
const documentHash = createHash("sha256").update(bytes).digest("hex");
|
|
79
79
|
documents.push({
|
|
@@ -116,6 +116,42 @@ export const analyzeInterfaceBuilderBundle = async (input) => {
|
|
|
116
116
|
omitted,
|
|
117
117
|
});
|
|
118
118
|
};
|
|
119
|
+
/** Select lexically earliest document paths independent of host traversal order. */
|
|
120
|
+
const selectInterfaceBuilderCandidates = async (reader, signal, maximumDocuments) => {
|
|
121
|
+
const capacity = maximumDocuments + MAX_REPORTED_OMITTED_ARCHIVES;
|
|
122
|
+
const candidates = [];
|
|
123
|
+
let total = 0;
|
|
124
|
+
for await (const entry of reader.entries(signal)) {
|
|
125
|
+
if (entry.kind !== "file" || !isInterfaceBuilderArchive(entry.path))
|
|
126
|
+
continue;
|
|
127
|
+
total += 1;
|
|
128
|
+
retainCandidate(candidates, entry, capacity);
|
|
129
|
+
}
|
|
130
|
+
const omittedSamples = candidates.slice(maximumDocuments, capacity);
|
|
131
|
+
return {
|
|
132
|
+
selected: candidates.slice(0, maximumDocuments),
|
|
133
|
+
omittedSamples,
|
|
134
|
+
omitted: Math.max(0, total - maximumDocuments),
|
|
135
|
+
unreportedOmitted: Math.max(0, total - maximumDocuments - omittedSamples.length),
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
/** Keep the earliest bounded path set; directory iteration order is host-defined. */
|
|
139
|
+
const retainCandidate = (candidates, entry, maximum) => {
|
|
140
|
+
let low = 0;
|
|
141
|
+
let high = candidates.length;
|
|
142
|
+
while (low < high) {
|
|
143
|
+
const middle = Math.floor((low + high) / 2);
|
|
144
|
+
const existing = candidates[middle];
|
|
145
|
+
if (existing !== undefined &&
|
|
146
|
+
compareUnicodeCodePoints(existing.path, entry.path) < 0)
|
|
147
|
+
low = middle + 1;
|
|
148
|
+
else
|
|
149
|
+
high = middle;
|
|
150
|
+
}
|
|
151
|
+
candidates.splice(low, 0, entry);
|
|
152
|
+
if (candidates.length > maximum)
|
|
153
|
+
candidates.pop();
|
|
154
|
+
};
|
|
119
155
|
const finalizeHierarchyCoverage = (result, counts) => {
|
|
120
156
|
const { incompleteHierarchies, prototypeKeyOmissions, invalid, omittedArchives, unreportedOmittedArchives, } = counts;
|
|
121
157
|
const archiveDecodePartial = invalid.length > 0 ||
|
|
@@ -452,9 +488,13 @@ const readEntry = async (reader, entry, signal, maxInputBytes = MAX_AGGREGATE_IN
|
|
|
452
488
|
return Buffer.concat(chunks, length);
|
|
453
489
|
};
|
|
454
490
|
/** Project decoded plist data and dates while retaining omitted-key coverage. */
|
|
455
|
-
const decodePlist = (bytes, xmlText) => {
|
|
456
|
-
const
|
|
457
|
-
|
|
491
|
+
const decodePlist = (bytes, xmlText, binaryPrototypeKeyObserved) => {
|
|
492
|
+
const binary = bytes.subarray(0, 8).toString("ascii") === "bplist00";
|
|
493
|
+
const { value, omittedPrototypeKeys } = binary
|
|
494
|
+
? {
|
|
495
|
+
value: parseBinary(bytes),
|
|
496
|
+
omittedPrototypeKeys: binaryPrototypeKeyObserved ? null : 0,
|
|
497
|
+
}
|
|
458
498
|
: parseXmlPropertyList(xmlText ?? decodeXmlPlistText(bytes));
|
|
459
499
|
return { value: projectPlistValue(value).value, omittedPrototypeKeys };
|
|
460
500
|
};
|
|
@@ -58,13 +58,16 @@ export class InterfaceBuilderDecodeBudget {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
/** Preflight the representation created by the pinned plist decoder. */
|
|
61
|
-
export const
|
|
62
|
-
const
|
|
61
|
+
export const preflightPropertyListDecode = (bytes, maxBytes, xmlText) => {
|
|
62
|
+
const expansion = bytes.subarray(0, 8).toString("ascii") === "bplist00"
|
|
63
63
|
? estimateBinaryPlistExpansion(bytes, maxBytes)
|
|
64
|
-
:
|
|
65
|
-
|
|
64
|
+
: {
|
|
65
|
+
estimatedBytes: estimateXmlPlistExpansion(bytes, maxBytes, xmlText),
|
|
66
|
+
binaryPrototypeKeyObserved: false,
|
|
67
|
+
};
|
|
68
|
+
if (expansion.estimatedBytes > maxBytes)
|
|
66
69
|
throw new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", "plist representation exceeds the aggregate Interface Builder decode budget");
|
|
67
|
-
return
|
|
70
|
+
return expansion;
|
|
68
71
|
};
|
|
69
72
|
const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
|
|
70
73
|
const xml = xmlText ?? decodeXmlPlistText(bytes);
|
|
@@ -94,8 +97,14 @@ const estimateXmlPlistExpansion = (bytes, maxBytes, xmlText) => {
|
|
|
94
97
|
}
|
|
95
98
|
return decodedSourceBytes * 2 + elementCount * 128;
|
|
96
99
|
};
|
|
97
|
-
|
|
98
|
-
const
|
|
100
|
+
const interfaceBuilderBudgetFailure = (_kind, message) => new InterfaceBuilderDecodeBudgetExceeded("aggregate_decode_budget_exhausted", message);
|
|
101
|
+
const PROTOTYPE_KEY = "__proto__";
|
|
102
|
+
/**
|
|
103
|
+
* Count every expanded binary-plist reference before calling plist.parseBinary,
|
|
104
|
+
* which recurses on each reference and copies shared containers. Malformed
|
|
105
|
+
* structure throws TypeError; budget, depth, and cycle failures use `fail`.
|
|
106
|
+
*/
|
|
107
|
+
export const estimateBinaryPlistExpansion = (bytes, maxBytes, { budget = "the aggregate Interface Builder decode budget", fail = interfaceBuilderBudgetFailure, bounds = "strict", } = {}) => {
|
|
99
108
|
if (bytes.length < 40)
|
|
100
109
|
throw new TypeError("binary plist trailer is truncated");
|
|
101
110
|
const trailer = bytes.length - 32;
|
|
@@ -115,19 +124,20 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
|
|
|
115
124
|
const objectCount = readInteger(trailer + 8, 8);
|
|
116
125
|
const topObject = readInteger(trailer + 16, 8);
|
|
117
126
|
const offsetTable = readInteger(trailer + 24, 8);
|
|
127
|
+
const tableEnd = bounds === "strict" ? trailer : bytes.length;
|
|
128
|
+
const objectsEnd = bounds === "strict" ? offsetTable : bytes.length;
|
|
118
129
|
if (objectCount < 1 ||
|
|
119
130
|
topObject < 0 ||
|
|
120
131
|
topObject >= objectCount ||
|
|
121
132
|
offsetTable < 8 ||
|
|
122
|
-
offsetTable + objectCount * offsetSize >
|
|
133
|
+
offsetTable + objectCount * offsetSize > tableEnd)
|
|
123
134
|
throw new TypeError("binary plist trailer or object table is invalid");
|
|
124
135
|
let estimate = bytes.length * 2 + objectCount * 16;
|
|
136
|
+
let binaryPrototypeKeyObserved = false;
|
|
125
137
|
if (estimate > maxBytes)
|
|
126
|
-
throw
|
|
138
|
+
throw fail("expansion", `binary plist object table exceeds ${budget}`);
|
|
127
139
|
const active = new Set();
|
|
128
|
-
const pending = [
|
|
129
|
-
{ object: topObject, depth: 0, exit: false },
|
|
130
|
-
];
|
|
140
|
+
const pending = [{ object: topObject, depth: 0, exit: false, dictionaryKey: false }];
|
|
131
141
|
let pendingObjectCount = 1;
|
|
132
142
|
while (pending.length > 0) {
|
|
133
143
|
const entry = pending.pop();
|
|
@@ -139,14 +149,14 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
|
|
|
139
149
|
}
|
|
140
150
|
pendingObjectCount -= 1;
|
|
141
151
|
if (entry.depth > 128)
|
|
142
|
-
throw
|
|
152
|
+
throw fail("depth", `binary plist nesting exceeds ${budget}`);
|
|
143
153
|
if (active.has(entry.object))
|
|
144
|
-
throw
|
|
154
|
+
throw fail("cycle", `binary plist reference cycle exceeds ${budget}`);
|
|
145
155
|
estimate += 96;
|
|
146
156
|
if (estimate > maxBytes)
|
|
147
|
-
throw
|
|
157
|
+
throw fail("expansion", `binary plist reference expansion exceeds ${budget}`);
|
|
148
158
|
const offset = readInteger(offsetTable + entry.object * offsetSize, offsetSize);
|
|
149
|
-
if (offset < 8 || offset >=
|
|
159
|
+
if (offset < 8 || offset >= objectsEnd)
|
|
150
160
|
throw new TypeError("binary plist object offset is invalid");
|
|
151
161
|
const marker = bytes[offset] ?? 0;
|
|
152
162
|
const type = marker >> 4;
|
|
@@ -160,36 +170,64 @@ const estimateBinaryPlistExpansion = (bytes, maxBytes) => {
|
|
|
160
170
|
const integerSize = 1 << (extMarker & 0x0f);
|
|
161
171
|
size = readInteger(cursor, integerSize);
|
|
162
172
|
cursor += integerSize;
|
|
163
|
-
if (size < 0 || cursor >
|
|
173
|
+
if (size < 0 || cursor > objectsEnd)
|
|
164
174
|
throw new TypeError("binary plist extended object size is invalid");
|
|
165
175
|
}
|
|
166
176
|
if (type === 4 || type === 5 || type === 6) {
|
|
167
177
|
const byteLength = type === 6 ? size * 2 : size;
|
|
168
|
-
if (cursor + byteLength >
|
|
178
|
+
if (cursor + byteLength > objectsEnd)
|
|
169
179
|
throw new TypeError("binary plist scalar object is truncated");
|
|
180
|
+
if (!binaryPrototypeKeyObserved &&
|
|
181
|
+
entry.dictionaryKey &&
|
|
182
|
+
(type === 5 || type === 6) &&
|
|
183
|
+
size === PROTOTYPE_KEY.length) {
|
|
184
|
+
let matches = true;
|
|
185
|
+
for (let index = 0; index < PROTOTYPE_KEY.length; index += 1) {
|
|
186
|
+
const codeUnit = type === 5
|
|
187
|
+
? (bytes[cursor + index] ?? 0)
|
|
188
|
+
: ((bytes[cursor + index * 2] ?? 0) << 8) |
|
|
189
|
+
(bytes[cursor + index * 2 + 1] ?? 0);
|
|
190
|
+
if (codeUnit !== PROTOTYPE_KEY.charCodeAt(index)) {
|
|
191
|
+
matches = false;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (matches)
|
|
196
|
+
binaryPrototypeKeyObserved = true;
|
|
197
|
+
}
|
|
170
198
|
estimate += type === 4 ? size + 4 * Math.ceil(size / 3) : byteLength * 2;
|
|
171
199
|
if (estimate > maxBytes)
|
|
172
|
-
throw
|
|
200
|
+
throw fail("expansion", `binary plist scalar expansion exceeds ${budget}`);
|
|
173
201
|
continue;
|
|
174
202
|
}
|
|
175
203
|
if (type !== 10 && type !== 13)
|
|
176
204
|
continue;
|
|
177
205
|
const childCount = type === 13 ? size * 2 : size;
|
|
178
206
|
const refsEnd = cursor + childCount * referenceSize;
|
|
179
|
-
if (!Number.isSafeInteger(refsEnd) || refsEnd >
|
|
207
|
+
if (!Number.isSafeInteger(refsEnd) || refsEnd > objectsEnd)
|
|
180
208
|
throw new TypeError("binary plist reference table is truncated");
|
|
181
209
|
const availableNodes = Math.floor((maxBytes - estimate) / 96);
|
|
182
210
|
if (childCount > availableNodes - pendingObjectCount)
|
|
183
|
-
throw
|
|
211
|
+
throw fail("expansion", `binary plist reference expansion exceeds ${budget}`);
|
|
184
212
|
active.add(entry.object);
|
|
185
|
-
pending.push({
|
|
213
|
+
pending.push({
|
|
214
|
+
object: entry.object,
|
|
215
|
+
depth: entry.depth,
|
|
216
|
+
exit: true,
|
|
217
|
+
dictionaryKey: false,
|
|
218
|
+
});
|
|
186
219
|
for (let index = childCount - 1; index >= 0; index -= 1) {
|
|
187
220
|
const reference = readInteger(cursor + index * referenceSize, referenceSize);
|
|
188
221
|
if (reference < 0 || reference >= objectCount)
|
|
189
222
|
throw new TypeError("binary plist reference is invalid");
|
|
190
|
-
pending.push({
|
|
223
|
+
pending.push({
|
|
224
|
+
object: reference,
|
|
225
|
+
depth: entry.depth + 1,
|
|
226
|
+
exit: false,
|
|
227
|
+
dictionaryKey: type === 13 && index < size,
|
|
228
|
+
});
|
|
191
229
|
}
|
|
192
230
|
pendingObjectCount += childCount;
|
|
193
231
|
}
|
|
194
|
-
return estimate;
|
|
232
|
+
return { estimatedBytes: estimate, binaryPrototypeKeyObserved };
|
|
195
233
|
};
|
|
@@ -11,7 +11,10 @@ import { KeyedArchiveKindError, keyedArchiveInputSchema, keyedArchiveResultSchem
|
|
|
11
11
|
import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
|
|
12
12
|
import { ArtifactReaderFailure } from "../ArtifactReader.js";
|
|
13
13
|
import { decodeXmlPlistText } from "../../domain/propertyListXmlText.js";
|
|
14
|
+
import { estimateBinaryPlistExpansion } from "./InterfaceBuilderDecodeBudget.js";
|
|
14
15
|
const MAX_BYTES = 64 * 1024 * 1024;
|
|
16
|
+
/** Decoded representation budget, the same 8:1 ratio Interface Builder uses. */
|
|
17
|
+
const MAX_DECODE_BYTES = 8 * MAX_BYTES;
|
|
15
18
|
/** Parse inert plist bytes, preserving data and dates with explicit typed values. */
|
|
16
19
|
export const decodeKeyedArchiveBytes = (bytes, selection) => {
|
|
17
20
|
if (bytes.length > MAX_BYTES)
|
|
@@ -20,8 +23,25 @@ export const decodeKeyedArchiveBytes = (bytes, selection) => {
|
|
|
20
23
|
throw new KeyedArchiveKindError("Selected file is a compiled NIBArchive, not a Foundation plist archive; decode it with decode_interface_builder", "nib-archive");
|
|
21
24
|
const binary = bytes.subarray(0, 8).toString("ascii") === "bplist00";
|
|
22
25
|
const xmlText = binary ? undefined : decodeXmlPlistText(bytes);
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
// plist.parseBinary recurses on every object reference and copies shared
|
|
27
|
+
// containers, so a few hundred bytes can exhaust memory or the stack.
|
|
28
|
+
// RangeError reports a resource limit; a reference cycle is malformed.
|
|
29
|
+
const binaryExpansion = binary
|
|
30
|
+
? estimateBinaryPlistExpansion(bytes, MAX_DECODE_BYTES, {
|
|
31
|
+
budget: "the keyed archive decode budget",
|
|
32
|
+
fail: (kind, message) => kind === "cycle"
|
|
33
|
+
? new TypeError("binary plist object references form a cycle, which a property list cannot represent")
|
|
34
|
+
: new RangeError(message),
|
|
35
|
+
bounds: "decoder",
|
|
36
|
+
})
|
|
37
|
+
: undefined;
|
|
38
|
+
const parsed = binaryExpansion !== undefined
|
|
39
|
+
? {
|
|
40
|
+
value: parseBinary(bytes),
|
|
41
|
+
omittedPrototypeKeys: binaryExpansion.binaryPrototypeKeyObserved
|
|
42
|
+
? null
|
|
43
|
+
: 0,
|
|
44
|
+
}
|
|
25
45
|
: parseXmlPropertyList(xmlText ?? "");
|
|
26
46
|
const { value: plistValue, unknownRealCount } = projectPlistValue(parsed.value);
|
|
27
47
|
const graph = projectKeyedArchive(plistValue, selection);
|
|
@@ -82,21 +102,20 @@ export const inspectBundleKeyedArchive = async (input) => {
|
|
|
82
102
|
try {
|
|
83
103
|
// Match inventory spelling while retaining the raw path for I/O and evidence.
|
|
84
104
|
const wanted = selected.path.normalize("NFC");
|
|
85
|
-
|
|
86
|
-
for await (const
|
|
87
|
-
if (
|
|
105
|
+
let entry;
|
|
106
|
+
for await (const candidate of reader.entries(input.signal, (directory) => wanted.startsWith(`${directory.normalize("NFC")}/`))) {
|
|
107
|
+
if (candidate.path.normalize("NFC") !== wanted)
|
|
88
108
|
continue;
|
|
89
|
-
|
|
109
|
+
if (candidate.kind !== "file")
|
|
110
|
+
throw archivePathError("invalid_value", `Archive path selects a ${candidate.kind}, not a regular file: ${selected.path}`);
|
|
111
|
+
if ((candidate.declaredSize ?? 0) > MAX_BYTES)
|
|
112
|
+
throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
|
|
113
|
+
if (entry !== undefined)
|
|
114
|
+
throw archivePathError("invalid_value", `Archive path matches multiple Unicode-equivalent bundle entries; selection is ambiguous: ${selected.path}`);
|
|
115
|
+
entry = candidate;
|
|
90
116
|
}
|
|
91
|
-
if (matches.length > 1)
|
|
92
|
-
throw archivePathError("invalid_value", `Archive path matches ${String(matches.length)} Unicode-equivalent bundle entries; selection is ambiguous: ${selected.path}`);
|
|
93
|
-
const entry = matches[0];
|
|
94
117
|
if (entry === undefined)
|
|
95
118
|
throw archivePathError("invalid_value", `No regular file exists at ${selected.path} in the active app bundle.`);
|
|
96
|
-
if (entry.kind !== "file")
|
|
97
|
-
throw archivePathError("invalid_value", `Archive path selects a ${entry.kind}, not a regular file: ${selected.path}`);
|
|
98
|
-
if ((entry.declaredSize ?? 0) > MAX_BYTES)
|
|
99
|
-
throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
|
|
100
119
|
const stream = await reader.open(entry, input.signal);
|
|
101
120
|
const chunks = [];
|
|
102
121
|
let size = 0;
|