rea-agents 2.0.0 → 2.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 +103 -38
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/AndroidApplicationService.js +17 -0
- package/dist/application/AppleApplicationService.js +17 -0
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +24 -2
- package/dist/application/ClientRegistrationStatus.js +11 -4
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +1 -23
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +156 -238
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +23 -7
- package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +20 -37
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InventoryProjectionEvidence.js +41 -0
- package/dist/application/InvestigationProviders.js +12 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayService.js +182 -156
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessPairedExperiment.js +72 -0
- package/dist/application/ProjectPermissionStore.js +48 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +148 -260
- package/dist/application/SetupClientConfiguration.js +224 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +124 -12
- package/dist/application/SetupSkill.js +54 -36
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +12 -3
- package/dist/application/Upgrade.js +16 -1
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +29 -496
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -133
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +4 -0
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +113 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +10 -768
- package/dist/cliApplicationCommands.js +118 -4
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +4 -0
- package/dist/cliElectronCommands.js +33 -62
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +306 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -375
- package/dist/contracts/applicationToolContracts.js +134 -0
- package/dist/contracts/electronToolContracts.js +51 -3
- package/dist/contracts/managedToolContracts.js +8 -3
- package/dist/contracts/managedWorkflowToolContracts.js +3 -3
- package/dist/contracts/providerSelection.js +2 -0
- package/dist/contracts/sessionStatusContract.js +26 -0
- package/dist/contracts/toolContractTypes.js +12 -1
- package/dist/contracts/toolContracts.js +5 -12
- package/dist/contracts/toolEffects.js +14 -0
- package/dist/contracts/toolOutputSchemaGroups.js +274 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
- package/dist/contracts/toolOutputSchemas.js +2 -550
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/androidApplication.js +206 -0
- package/dist/domain/appleApplication.js +221 -0
- package/dist/domain/artifactComparison.js +34 -15
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/boundedCartesianProjection.js +15 -0
- package/dist/domain/browserObservation.js +1 -285
- package/dist/domain/browserObservationSchemas.js +286 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
- package/dist/domain/errors.js +4 -486
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/javascriptApplicationVersionItems.js +18 -6
- package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
- package/dist/domain/javascriptExportInstrumentation.js +97 -0
- package/dist/domain/javascriptFeatureTraversal.js +19 -7
- package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +5 -221
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +14 -364
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +16 -8
- package/dist/domain/managedMemberComparison.js +37 -391
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +27 -389
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +82 -69
- package/dist/domain/managedRuntimeCorrelation.js +12 -3
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/processComparison.js +19 -0
- package/dist/domain/processPairedExperiment.js +128 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +8 -0
- package/dist/domain/replayMachine.js +316 -0
- package/dist/domain/replayMachineRuntime.js +215 -0
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/runtimeIdentification.js +210 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +50 -29
- package/dist/dotnet/ManagedMemberInspector.js +51 -785
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataInventory.js +42 -306
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +48 -111
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
- package/dist/dotnet/ManagedPeReader.js +59 -28
- package/dist/evaluation/CodexAgentEval.js +132 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +61 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +4 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -146
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +64 -50
- package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +124 -56
- package/dist/server/javascriptApplicationResult.js +85 -0
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +10 -112
- package/dist/server/registerBrowserTools.js +59 -83
- package/dist/server/registerElectronTools.js +48 -49
- package/dist/server/registerEnhancedTools.js +34 -42
- package/dist/server/registerEvidenceResources.js +56 -0
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +83 -116
- package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
- package/dist/server/registerManagedTools.js +18 -1
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +10 -274
- package/dist/server/registerOfficialTools.js +73 -59
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +97 -26
- package/dist/server/registerSessionTools.js +60 -164
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/toolRegistrationOptions.js +101 -3
- package/dist/server/toolResult.js +15 -4
- package/package.json +11 -11
- package/skills/reverse-engineer-anything/SKILL.md +76 -0
- package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
- package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
- package/skills/rea-analysis/SKILL.md +0 -222
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
|
-
import { createReadStream } from "node:fs";
|
|
3
2
|
import { createHash } from "node:crypto";
|
|
4
3
|
import { access, open, readFile, realpath, stat, } from "node:fs/promises";
|
|
5
4
|
import { execFile } from "node:child_process";
|
|
@@ -22,43 +21,42 @@ export const parseBinaryTarget = async (input, cwd = process.cwd(), hostArchitec
|
|
|
22
21
|
if (!resolved.ok)
|
|
23
22
|
return err(resolved.error);
|
|
24
23
|
const path = resolved.value;
|
|
25
|
-
if (!(await stat(path)).isFile())
|
|
26
|
-
return err(new BinaryTargetError(path, "target is not a regular file"));
|
|
27
|
-
if (targetKind === "database" ||
|
|
28
|
-
(targetKind === undefined && path.toLowerCase().endsWith(".hop")))
|
|
29
|
-
return ok({
|
|
30
|
-
path,
|
|
31
|
-
sourcePath: canonical,
|
|
32
|
-
sha256: await sha256File(path),
|
|
33
|
-
kind: "database",
|
|
34
|
-
format: "analysis-database",
|
|
35
|
-
});
|
|
36
24
|
const handle = await open(path, "r");
|
|
37
|
-
let detected;
|
|
38
25
|
try {
|
|
26
|
+
if (!(await handle.stat()).isFile())
|
|
27
|
+
return err(new BinaryTargetError(path, "target is not a regular file"));
|
|
28
|
+
if (targetKind === "database" ||
|
|
29
|
+
(targetKind === undefined && path.toLowerCase().endsWith(".hop")))
|
|
30
|
+
return ok({
|
|
31
|
+
path,
|
|
32
|
+
sourcePath: canonical,
|
|
33
|
+
sha256: await sha256Handle(handle),
|
|
34
|
+
kind: "database",
|
|
35
|
+
format: "analysis-database",
|
|
36
|
+
});
|
|
39
37
|
const artifactFormat = await detectArtifactFormat(path, handle);
|
|
40
38
|
if (artifactFormat !== undefined)
|
|
41
39
|
return ok({
|
|
42
40
|
path,
|
|
43
41
|
sourcePath: canonical,
|
|
44
|
-
sha256: await
|
|
42
|
+
sha256: await sha256Handle(handle),
|
|
45
43
|
kind: isArchiveFormat(artifactFormat) ? "archive" : "artifact",
|
|
46
44
|
format: artifactFormat,
|
|
47
45
|
});
|
|
48
|
-
detected = await readExecutableMetadata(handle, hostArchitecture);
|
|
46
|
+
const detected = await readExecutableMetadata(handle, hostArchitecture);
|
|
47
|
+
if (!detected.ok)
|
|
48
|
+
return err(new BinaryTargetError(path, detected.error));
|
|
49
|
+
return ok({
|
|
50
|
+
path,
|
|
51
|
+
sourcePath: canonical,
|
|
52
|
+
sha256: await sha256Handle(handle),
|
|
53
|
+
kind: "executable",
|
|
54
|
+
...detected.value,
|
|
55
|
+
});
|
|
49
56
|
}
|
|
50
57
|
finally {
|
|
51
58
|
await handle.close();
|
|
52
59
|
}
|
|
53
|
-
if (!detected.ok)
|
|
54
|
-
return err(new BinaryTargetError(path, detected.error));
|
|
55
|
-
return ok({
|
|
56
|
-
path,
|
|
57
|
-
sourcePath: canonical,
|
|
58
|
-
sha256: await sha256File(path),
|
|
59
|
-
kind: "executable",
|
|
60
|
-
...detected.value,
|
|
61
|
-
});
|
|
62
60
|
}
|
|
63
61
|
catch (cause) {
|
|
64
62
|
return err(new BinaryTargetError(candidate, "path is not readable", { cause }));
|
|
@@ -107,10 +105,17 @@ const namedArtifactFormat = (lowerPath) => {
|
|
|
107
105
|
return /\.(?:m?js|cjs)$/u.test(lowerPath) ? "javascript" : undefined;
|
|
108
106
|
};
|
|
109
107
|
const isArchiveFormat = (format) => ["zip", "ipa", "apk", "asar", "dmg", "pkg"].includes(format);
|
|
110
|
-
const
|
|
108
|
+
const sha256Handle = async (handle) => {
|
|
111
109
|
const hash = createHash("sha256");
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const chunk = Buffer.allocUnsafe(64 * 1024);
|
|
111
|
+
let position = 0;
|
|
112
|
+
while (true) {
|
|
113
|
+
const observed = await handle.read(chunk, 0, chunk.length, position);
|
|
114
|
+
if (observed.bytesRead === 0)
|
|
115
|
+
break;
|
|
116
|
+
hash.update(chunk.subarray(0, observed.bytesRead));
|
|
117
|
+
position += observed.bytesRead;
|
|
118
|
+
}
|
|
114
119
|
return hash.digest("hex");
|
|
115
120
|
};
|
|
116
121
|
const resolveAppBundle = async (path) => {
|
|
@@ -184,13 +189,7 @@ const readExecutableMetadata = async (handle, hostArchitecture) => {
|
|
|
184
189
|
const bytes = prefix.subarray(0, prefixRead.bytesRead);
|
|
185
190
|
if (bytes.length >= 64 && bytes[0] === 0x4d && bytes[1] === 0x5a) {
|
|
186
191
|
const offset = bytes.readUInt32LE(0x3c);
|
|
187
|
-
|
|
188
|
-
const record = Buffer.alloc(6);
|
|
189
|
-
const recordRead = await handle.read(record, 0, record.length, offset);
|
|
190
|
-
return recordRead.bytesRead === record.length
|
|
191
|
-
? parsePeRecord(record)
|
|
192
|
-
: err("invalid or truncated PE header");
|
|
193
|
-
}
|
|
192
|
+
return readPeMetadata(handle, offset);
|
|
194
193
|
}
|
|
195
194
|
if (bytes.length >= 8) {
|
|
196
195
|
const magic = bytes.readUInt32BE(0);
|
|
@@ -207,6 +206,20 @@ const readExecutableMetadata = async (handle, hostArchitecture) => {
|
|
|
207
206
|
}
|
|
208
207
|
return parseExecutableHeader(bytes, hostArchitecture);
|
|
209
208
|
};
|
|
209
|
+
const readPeMetadata = async (handle, offset) => {
|
|
210
|
+
const fileHeader = Buffer.alloc(24);
|
|
211
|
+
const fileHeaderRead = await handle.read(fileHeader, 0, fileHeader.length, offset);
|
|
212
|
+
if (fileHeaderRead.bytesRead !== fileHeader.length)
|
|
213
|
+
return err("invalid or truncated PE header");
|
|
214
|
+
const optionalHeaderSize = fileHeader.readUInt16LE(20);
|
|
215
|
+
if (optionalHeaderSize > 4096)
|
|
216
|
+
return err("invalid PE optional header size");
|
|
217
|
+
const record = Buffer.alloc(24 + optionalHeaderSize);
|
|
218
|
+
const recordRead = await handle.read(record, 0, record.length, offset);
|
|
219
|
+
return recordRead.bytesRead === record.length
|
|
220
|
+
? parsePeRecord(record)
|
|
221
|
+
: err("invalid or truncated PE header");
|
|
222
|
+
};
|
|
210
223
|
/**
|
|
211
224
|
* Parse supported executable headers without I/O. The caller supplies the host
|
|
212
225
|
* architecture used for deterministic FAT Mach-O slice selection.
|
|
@@ -294,22 +307,59 @@ const parsePe = (bytes) => {
|
|
|
294
307
|
if (bytes.length < 64)
|
|
295
308
|
return err("truncated PE DOS header");
|
|
296
309
|
const offset = bytes.readUInt32LE(0x3c);
|
|
297
|
-
if (offset > bytes.length -
|
|
310
|
+
if (offset > bytes.length - 24)
|
|
298
311
|
return err("invalid or truncated PE header");
|
|
299
|
-
return parsePeRecord(bytes.subarray(offset
|
|
312
|
+
return parsePeRecord(bytes.subarray(offset));
|
|
300
313
|
};
|
|
301
314
|
const parsePeRecord = (record) => {
|
|
302
|
-
if (record.length <
|
|
315
|
+
if (record.length < 24 ||
|
|
316
|
+
record.toString("binary", 0, 4) !== "PE\u0000\u0000")
|
|
303
317
|
return err("invalid or truncated PE header");
|
|
304
318
|
const architecture = peArchitecture(record.readUInt16LE(4));
|
|
305
319
|
if (architecture === undefined)
|
|
306
320
|
return err("unsupported PE architecture");
|
|
321
|
+
const optionalHeaderSize = record.readUInt16LE(20);
|
|
322
|
+
if (optionalHeaderSize > 4096 || record.length < 24 + optionalHeaderSize)
|
|
323
|
+
return err("invalid or truncated PE optional header");
|
|
324
|
+
const optionalHeader = record.subarray(24, 24 + optionalHeaderSize);
|
|
325
|
+
const managed = peManagedStatus(optionalHeader, architecture);
|
|
326
|
+
if (!managed.ok)
|
|
327
|
+
return managed;
|
|
328
|
+
const characteristics = record.readUInt16LE(22);
|
|
307
329
|
return ok({
|
|
308
330
|
format: "pe",
|
|
309
331
|
architecture,
|
|
310
332
|
availableArchitectures: [architecture],
|
|
333
|
+
executableRole: (characteristics & 0x0002) === 0
|
|
334
|
+
? "non-executable"
|
|
335
|
+
: (characteristics & 0x2000) === 0
|
|
336
|
+
? "application"
|
|
337
|
+
: "shared-library",
|
|
338
|
+
managed: managed.value,
|
|
311
339
|
});
|
|
312
340
|
};
|
|
341
|
+
const peManagedStatus = (optionalHeader, architecture) => {
|
|
342
|
+
if (optionalHeader.length < 2)
|
|
343
|
+
return err("truncated PE optional header");
|
|
344
|
+
const magic = optionalHeader.readUInt16LE(0);
|
|
345
|
+
const expectedMagic = architecture === "x86_64" || architecture === "arm64" ? 0x20b : 0x10b;
|
|
346
|
+
if (magic !== expectedMagic)
|
|
347
|
+
return err("PE optional-header magic does not match its architecture");
|
|
348
|
+
const directoryOffset = magic === 0x20b ? 112 : 96;
|
|
349
|
+
const directoryCountOffset = directoryOffset - 4;
|
|
350
|
+
if (optionalHeader.length < directoryCountOffset + 4)
|
|
351
|
+
return err("truncated PE optional header");
|
|
352
|
+
const directoryCount = optionalHeader.readUInt32LE(directoryCountOffset);
|
|
353
|
+
const requiredBytes = directoryOffset + directoryCount * 8;
|
|
354
|
+
if (!Number.isSafeInteger(requiredBytes) ||
|
|
355
|
+
requiredBytes > optionalHeader.length)
|
|
356
|
+
return err("truncated PE data-directory table");
|
|
357
|
+
if (directoryCount <= 14)
|
|
358
|
+
return ok(false);
|
|
359
|
+
const cliDirectory = directoryOffset + 14 * 8;
|
|
360
|
+
return ok(optionalHeader.readUInt32LE(cliDirectory) !== 0 ||
|
|
361
|
+
optionalHeader.readUInt32LE(cliDirectory + 4) !== 0);
|
|
362
|
+
};
|
|
313
363
|
const machArchitecture = (cpu) => {
|
|
314
364
|
switch (cpu) {
|
|
315
365
|
case 7:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Project a Cartesian product without materializing values beyond the output limit. */
|
|
2
|
+
export const projectBoundedCartesian = (left, right, maximum, project) => {
|
|
3
|
+
const values = [];
|
|
4
|
+
for (const leftValue of left) {
|
|
5
|
+
for (const rightValue of right) {
|
|
6
|
+
if (values.length === maximum)
|
|
7
|
+
return {
|
|
8
|
+
values,
|
|
9
|
+
omitted: left.length * right.length - values.length,
|
|
10
|
+
};
|
|
11
|
+
values.push(project(leftValue, rightValue));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return { values, omitted: 0 };
|
|
15
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
import { webTextArtifactSchema } from "./webContentArtifact.js";
|
|
4
|
-
import { jsonShapeSchema } from "./jsonShape.js";
|
|
2
|
+
export { browserTargetListSchema, webPageInspectionSchema, } from "./browserObservationSchemas.js";
|
|
5
3
|
const parseExactOrigin = (value) => {
|
|
6
4
|
let url;
|
|
7
5
|
try {
|
|
@@ -306,285 +304,3 @@ export const sanitizeBrowserUrl = (value) => {
|
|
|
306
304
|
redacted: wasTruncated || hadCredentials || hadFragment || names.length > 0,
|
|
307
305
|
};
|
|
308
306
|
};
|
|
309
|
-
const browserVersionSchema = z.object({
|
|
310
|
-
product: z.string(),
|
|
311
|
-
protocol_version: z.string(),
|
|
312
|
-
revision: z.string(),
|
|
313
|
-
user_agent: z.string(),
|
|
314
|
-
js_version: z.string(),
|
|
315
|
-
});
|
|
316
|
-
const browserTargetSchema = z.object({
|
|
317
|
-
target_id: z.string(),
|
|
318
|
-
type: z.string(),
|
|
319
|
-
title: z.string(),
|
|
320
|
-
url: z.string(),
|
|
321
|
-
origin: z.string(),
|
|
322
|
-
attached: z.boolean(),
|
|
323
|
-
});
|
|
324
|
-
/** Bounded and policy-filtered browser target discovery result. */
|
|
325
|
-
export const browserTargetListSchema = z.object({
|
|
326
|
-
schema_version: z.literal(1),
|
|
327
|
-
browser: browserVersionSchema,
|
|
328
|
-
targets: z.object({
|
|
329
|
-
items: z.array(browserTargetSchema),
|
|
330
|
-
offset: z.number().int().min(0),
|
|
331
|
-
limit: z.number().int().min(1),
|
|
332
|
-
total: z.number().int().min(0),
|
|
333
|
-
next_offset: z.number().int().min(0).nullable(),
|
|
334
|
-
has_more: z.boolean(),
|
|
335
|
-
}),
|
|
336
|
-
excluded: z.object({
|
|
337
|
-
disallowed_origin: z.number().int().min(0),
|
|
338
|
-
unsupported_url: z.number().int().min(0),
|
|
339
|
-
non_page: z.number().int().min(0),
|
|
340
|
-
}),
|
|
341
|
-
limitations: z.array(z.string()),
|
|
342
|
-
});
|
|
343
|
-
const browserFrameSchema = z.object({
|
|
344
|
-
frame_id: z.string(),
|
|
345
|
-
parent_frame_id: z.string().nullable(),
|
|
346
|
-
url: z.string(),
|
|
347
|
-
origin: z.string().nullable(),
|
|
348
|
-
});
|
|
349
|
-
const browserDomNodeSchema = z.object({
|
|
350
|
-
index: z.number().int().min(0),
|
|
351
|
-
parent_index: z.number().int().min(-1),
|
|
352
|
-
node_type: z.number().int().min(0),
|
|
353
|
-
node_name: z.string(),
|
|
354
|
-
node_value_length: z.number().int().min(0),
|
|
355
|
-
attribute_names: z.array(z.string()),
|
|
356
|
-
});
|
|
357
|
-
const browserAxNodeSchema = z.object({
|
|
358
|
-
node_id: z.string(),
|
|
359
|
-
parent_id: z.string().nullable(),
|
|
360
|
-
role: z.string().nullable(),
|
|
361
|
-
name: z.string().nullable(),
|
|
362
|
-
description: z.string().nullable(),
|
|
363
|
-
ignored: z.boolean(),
|
|
364
|
-
});
|
|
365
|
-
const browserScriptSourceSchema = z.discriminatedUnion("included", [
|
|
366
|
-
z.object({ included: z.literal(false), reason: z.string() }),
|
|
367
|
-
z.object({
|
|
368
|
-
included: z.literal(true),
|
|
369
|
-
artifact: webTextArtifactSchema,
|
|
370
|
-
}),
|
|
371
|
-
]);
|
|
372
|
-
const browserResourceReconciliationSchema = z.discriminatedUnion("status", [
|
|
373
|
-
z.object({ status: z.literal("exact"), resource_key: z.string() }),
|
|
374
|
-
z.object({
|
|
375
|
-
status: z.literal("ambiguous"),
|
|
376
|
-
candidate_resource_keys: z.array(z.string()),
|
|
377
|
-
}),
|
|
378
|
-
z.object({
|
|
379
|
-
status: z.literal("unmatched"),
|
|
380
|
-
reason: z.literal("no_exact_sanitized_url"),
|
|
381
|
-
}),
|
|
382
|
-
]);
|
|
383
|
-
const browserScriptSchema = z.object({
|
|
384
|
-
script_key: z.string().regex(/^scr_[a-f0-9]{64}(?:_[0-9]+)?$/u),
|
|
385
|
-
frame_id: z.string().nullable().default(null),
|
|
386
|
-
url: z.string(),
|
|
387
|
-
origin: z.string().nullable(),
|
|
388
|
-
cdp_hash: z.string(),
|
|
389
|
-
length: z.number().int().min(0),
|
|
390
|
-
is_module: z.boolean(),
|
|
391
|
-
language: z.string().nullable(),
|
|
392
|
-
source_map_url: z.string().nullable(),
|
|
393
|
-
resource_reconciliation: browserResourceReconciliationSchema,
|
|
394
|
-
source: browserScriptSourceSchema,
|
|
395
|
-
});
|
|
396
|
-
const browserResourceSchema = z.object({
|
|
397
|
-
resource_key: z.string().regex(/^res_[a-f0-9]{64}$/u),
|
|
398
|
-
url: z.string(),
|
|
399
|
-
origin: z.string().nullable(),
|
|
400
|
-
type: z.string(),
|
|
401
|
-
mime_type: z.string(),
|
|
402
|
-
content_size: z.number().min(0).nullable(),
|
|
403
|
-
});
|
|
404
|
-
const browserNetworkRequestSchema = z.object({
|
|
405
|
-
request_id: z.string(),
|
|
406
|
-
url: z.string(),
|
|
407
|
-
origin: z.string().nullable(),
|
|
408
|
-
method: z.string(),
|
|
409
|
-
resource_type: z.string().nullable(),
|
|
410
|
-
status: z.number().nullable(),
|
|
411
|
-
mime_type: z.string().nullable(),
|
|
412
|
-
encoded_data_length: z.number().min(0).nullable(),
|
|
413
|
-
initiator: z.object({
|
|
414
|
-
type: z.string(),
|
|
415
|
-
url: z.string().nullable(),
|
|
416
|
-
line: z.number().int().min(0).nullable(),
|
|
417
|
-
column: z.number().int().min(0).nullable(),
|
|
418
|
-
}),
|
|
419
|
-
body_shapes: z.object({
|
|
420
|
-
status: z.enum([
|
|
421
|
-
"not_approved",
|
|
422
|
-
"included",
|
|
423
|
-
"partial",
|
|
424
|
-
"unavailable",
|
|
425
|
-
"truncated",
|
|
426
|
-
]),
|
|
427
|
-
request: jsonShapeSchema.nullable(),
|
|
428
|
-
response: jsonShapeSchema.nullable(),
|
|
429
|
-
}),
|
|
430
|
-
});
|
|
431
|
-
const browserConsoleEventSchema = z.object({
|
|
432
|
-
type: z.string(),
|
|
433
|
-
timestamp: z.number(),
|
|
434
|
-
argument_types: z.array(z.string()),
|
|
435
|
-
url: z.string().nullable(),
|
|
436
|
-
line: z.number().int().min(0).nullable(),
|
|
437
|
-
column: z.number().int().min(0).nullable(),
|
|
438
|
-
text_capture: z.object({
|
|
439
|
-
status: z.enum(["not_approved", "included", "truncated"]),
|
|
440
|
-
values: z.array(z.object({
|
|
441
|
-
argument_index: z.number().int().min(0),
|
|
442
|
-
type: z.string(),
|
|
443
|
-
text: z.string(),
|
|
444
|
-
})),
|
|
445
|
-
retained_bytes: z.number().int().min(0),
|
|
446
|
-
truncated_values: z.number().int().min(0),
|
|
447
|
-
}),
|
|
448
|
-
});
|
|
449
|
-
const browserWebSocketEventSchema = z.object({
|
|
450
|
-
request_id: z.string(),
|
|
451
|
-
direction: z.enum(["sent", "received"]),
|
|
452
|
-
opcode: z.number().int().min(0),
|
|
453
|
-
payload_bytes: z.number().int().min(0),
|
|
454
|
-
payload_shape: z
|
|
455
|
-
.object({
|
|
456
|
-
format: z.enum(["json", "text", "binary"]),
|
|
457
|
-
json_shape: jsonShapeSchema.nullable(),
|
|
458
|
-
truncated: z.boolean(),
|
|
459
|
-
})
|
|
460
|
-
.nullable(),
|
|
461
|
-
});
|
|
462
|
-
const browserWorkerSchema = z.object({
|
|
463
|
-
target_id: z.string(),
|
|
464
|
-
type: z.string(),
|
|
465
|
-
url: z.string(),
|
|
466
|
-
origin: z.string().nullable(),
|
|
467
|
-
attached: z.boolean(),
|
|
468
|
-
opener_target_id: z.string().nullable().default(null),
|
|
469
|
-
parent_frame_id: z.string().nullable().default(null),
|
|
470
|
-
});
|
|
471
|
-
const browserCspSourceSchema = z.object({
|
|
472
|
-
kind: z.enum([
|
|
473
|
-
"keyword",
|
|
474
|
-
"scheme",
|
|
475
|
-
"approved_origin",
|
|
476
|
-
"external_origin",
|
|
477
|
-
"other",
|
|
478
|
-
]),
|
|
479
|
-
value: z.string().nullable(),
|
|
480
|
-
});
|
|
481
|
-
const browserLinkMetadataSchema = z.object({
|
|
482
|
-
href: z.string().nullable(),
|
|
483
|
-
destination_scope: z.enum(["approved", "outside_policy", "unsupported"]),
|
|
484
|
-
rel: z.array(z.string()),
|
|
485
|
-
as: z.string().nullable(),
|
|
486
|
-
type: z.string().nullable(),
|
|
487
|
-
crossorigin: z.string().nullable(),
|
|
488
|
-
});
|
|
489
|
-
const browserAgentHintSchema = z.object({
|
|
490
|
-
mechanism: z.enum([
|
|
491
|
-
"link_rel",
|
|
492
|
-
"dom_link_rel",
|
|
493
|
-
"well_known_resource",
|
|
494
|
-
"response_header",
|
|
495
|
-
]),
|
|
496
|
-
declaration: z.string(),
|
|
497
|
-
url: z.string().nullable(),
|
|
498
|
-
trust: z.literal("page-declared-untrusted"),
|
|
499
|
-
});
|
|
500
|
-
const browserSafeMetadataSchema = z.object({
|
|
501
|
-
responses: z.array(z.object({
|
|
502
|
-
request_id: z.string(),
|
|
503
|
-
url: z.string(),
|
|
504
|
-
mime_type: z.string().nullable(),
|
|
505
|
-
content_length: z.number().int().min(0).nullable(),
|
|
506
|
-
content_encoding: z.string().nullable(),
|
|
507
|
-
csp: z.object({
|
|
508
|
-
directives: z.array(z.object({
|
|
509
|
-
name: z.string(),
|
|
510
|
-
sources: z.array(browserCspSourceSchema),
|
|
511
|
-
})),
|
|
512
|
-
nonce_count: z.number().int().min(0),
|
|
513
|
-
hash_count: z.number().int().min(0),
|
|
514
|
-
}),
|
|
515
|
-
links: z.array(browserLinkMetadataSchema),
|
|
516
|
-
policies: z.object({
|
|
517
|
-
coop: z.string().nullable(),
|
|
518
|
-
coep: z.string().nullable(),
|
|
519
|
-
corp: z.string().nullable(),
|
|
520
|
-
referrer_policy: z.string().nullable(),
|
|
521
|
-
x_content_type_options: z.string().nullable(),
|
|
522
|
-
permissions_policy_features: z.array(z.string()),
|
|
523
|
-
}),
|
|
524
|
-
})),
|
|
525
|
-
dom_urls: z.array(z.object({
|
|
526
|
-
node_index: z.number().int().min(0),
|
|
527
|
-
attribute: z.enum(["href", "src", "action", "formaction", "poster"]),
|
|
528
|
-
url: z.string().nullable(),
|
|
529
|
-
destination_scope: z.enum(["approved", "outside_policy", "unsupported"]),
|
|
530
|
-
})),
|
|
531
|
-
agent_hints: z.array(browserAgentHintSchema),
|
|
532
|
-
excluded_dom_urls: z.number().int().min(0),
|
|
533
|
-
headers_allowlisted: z.literal(true),
|
|
534
|
-
});
|
|
535
|
-
/** Provider-neutral normalized result for one passive web-page observation. */
|
|
536
|
-
export const webPageInspectionSchema = z.object({
|
|
537
|
-
schema_version: z.literal(2),
|
|
538
|
-
browser: browserVersionSchema,
|
|
539
|
-
target: browserTargetSchema,
|
|
540
|
-
capture_window: z.object({
|
|
541
|
-
started_at: z.iso.datetime(),
|
|
542
|
-
ended_at: z.iso.datetime(),
|
|
543
|
-
observation_ms: z.number().int().min(0),
|
|
544
|
-
}),
|
|
545
|
-
completeness: browserCompletenessSchema,
|
|
546
|
-
frames: z.array(browserFrameSchema),
|
|
547
|
-
dom: z.object({
|
|
548
|
-
total_nodes: z.number().int().min(0),
|
|
549
|
-
nodes: z.array(browserDomNodeSchema),
|
|
550
|
-
}),
|
|
551
|
-
accessibility: z.object({
|
|
552
|
-
total_nodes: z.number().int().min(0),
|
|
553
|
-
text_capture: z.object({
|
|
554
|
-
status: z.enum(["not_approved", "included", "truncated", "unavailable"]),
|
|
555
|
-
retained_bytes: z.number().int().min(0),
|
|
556
|
-
excluded_fields: z.number().int().min(0),
|
|
557
|
-
truncated_fields: z.number().int().min(0),
|
|
558
|
-
}),
|
|
559
|
-
nodes: z.array(browserAxNodeSchema),
|
|
560
|
-
}),
|
|
561
|
-
scripts: z.object({
|
|
562
|
-
total: z.number().int().min(0),
|
|
563
|
-
items: z.array(browserScriptSchema),
|
|
564
|
-
}),
|
|
565
|
-
resources: z.array(browserResourceSchema),
|
|
566
|
-
network: z.object({
|
|
567
|
-
requests: z.array(browserNetworkRequestSchema),
|
|
568
|
-
websocket_events: z.array(browserWebSocketEventSchema),
|
|
569
|
-
coverage_started_at: z.iso.datetime(),
|
|
570
|
-
prior_activity_available: z.literal(false),
|
|
571
|
-
}),
|
|
572
|
-
console: z.object({
|
|
573
|
-
events: z.array(browserConsoleEventSchema),
|
|
574
|
-
coverage_started_at: z.iso.datetime(),
|
|
575
|
-
prior_activity_available: z.literal(false),
|
|
576
|
-
}),
|
|
577
|
-
workers: z.array(browserWorkerSchema),
|
|
578
|
-
metadata: browserSafeMetadataSchema,
|
|
579
|
-
storage: z.object({
|
|
580
|
-
origin: z.string(),
|
|
581
|
-
usage_bytes: z.number().min(0).nullable(),
|
|
582
|
-
quota_bytes: z.number().min(0).nullable(),
|
|
583
|
-
local_storage_keys: z.array(z.string()),
|
|
584
|
-
session_storage_keys: z.array(z.string()),
|
|
585
|
-
indexed_db_names: z.array(z.string()),
|
|
586
|
-
cache_names: z.array(z.string()),
|
|
587
|
-
values_redacted: z.literal(true),
|
|
588
|
-
}),
|
|
589
|
-
limitations: z.array(z.string()),
|
|
590
|
-
});
|