mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
feat(artifacts): inventory and extract Node.js single executable application blobs (#7000)
* feat(artifacts): inventory and extract Node.js single executable application blobs Adds a node-sea artifact reader that locates the NODE_SEA_BLOB payload in Mach-O sections, ELF notes and PE RCDATA resources, decodes the blob header, main script, optional snapshot and code cache, and named assets, and extracts their stored bytes through the existing safe output tree. The executable is never run. Resource-tree errors in a PE without a NODE_SEA_BLOB name stay with native classification; truncated, unknown or over-limit SEA declarations fail closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe * fix(artifacts): reuse PE resource facts and bound SEA asset tables Move the bounded NODE_SEA_BLOB name probe into the shared PE resource layout module so SEA admission uses the same header and section mapping as the full parser; the layout reader now accepts a header prefix with the file size. Bound SEA asset count and decoded name bytes before records are created and report resource bounds as limit failures. Offer the JavaScript next probe only for main scripts with a source suffix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016y53PdpyMAp9RSW65fatHe * fix(artifacts): make SEA metadata construction cancellable --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
26 files changed
+3151
-17
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
// Requires a running Docker daemon, network access for the pinned fixture
|
||||
// producer, and `npm run build:cached`. Never executes the injected application.
|
||||
const root = await mkdtemp(join(tmpdir(), "rea-node-sea-real-"));
|
||||
const image = "node:24.10.0-bookworm";
|
||||
const script =
|
||||
'throw new Error("SEA verification must not execute this application");\n';
|
||||
try {
|
||||
await writeFile(join(root, "main.js"), script);
|
||||
await writeFile(join(root, "asset.txt"), "real SEA asset\n");
|
||||
await writeFile(
|
||||
join(root, "sea.json"),
|
||||
JSON.stringify({
|
||||
main: "main.js",
|
||||
output: "sea.blob",
|
||||
disableExperimentalSEAWarning: true,
|
||||
useCodeCache: true,
|
||||
assets: { "data/asset.txt": "asset.txt" },
|
||||
}),
|
||||
);
|
||||
execFileSync(
|
||||
"docker",
|
||||
[
|
||||
"run",
|
||||
"--rm",
|
||||
"--volume",
|
||||
`${root}:/fixture`,
|
||||
"--workdir",
|
||||
"/fixture",
|
||||
image,
|
||||
"sh",
|
||||
"-ec",
|
||||
"node --experimental-sea-config sea.json; cp /usr/local/bin/node application; npx --yes postject@1.0.0-alpha.6 application NODE_SEA_BLOB sea.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2",
|
||||
],
|
||||
{ stdio: "inherit", timeout: 300_000 },
|
||||
);
|
||||
const cli = (...args) =>
|
||||
JSON.parse(
|
||||
execFileSync(
|
||||
process.execPath,
|
||||
[resolve("scripts/rea.mjs"), ...args, "--json"],
|
||||
{
|
||||
encoding: "utf8",
|
||||
timeout: 120_000,
|
||||
maxBuffer: 16 * 1024 * 1024,
|
||||
env: { ...process.env, TMPDIR: root, TMP: root, TEMP: root },
|
||||
},
|
||||
),
|
||||
);
|
||||
const input = join(root, "application");
|
||||
const inspected = cli("inspect-artifact", input);
|
||||
const graph =
|
||||
inspected.normalized_result.substeps[0].evidence.normalized_result;
|
||||
assert.equal(graph.manifest.root_format, "node-sea");
|
||||
const metadata = graph.occurrences.find(
|
||||
(row) => row.logical_path === ".",
|
||||
).format_metadata;
|
||||
assert.equal(metadata.fuse_state, "set");
|
||||
assert.equal(metadata.use_code_cache, true);
|
||||
assert.equal(metadata.include_assets, true);
|
||||
const extracted = cli("extract-artifact", input).normalized_result;
|
||||
assert.equal(extracted.containment_verified, true);
|
||||
assert.equal(
|
||||
await readFile(join(extracted.output_root, "main.js"), "utf8"),
|
||||
script,
|
||||
);
|
||||
assert.equal(
|
||||
await readFile(join(extracted.output_root, "data/asset.txt"), "utf8"),
|
||||
"real SEA asset\n",
|
||||
);
|
||||
process.stdout.write(
|
||||
`${JSON.stringify({ producer: image, metadata, verified: ["ELF inventory", "code cache", "fuse", "script extraction", "asset extraction"] }, null, 2)}\n`,
|
||||
);
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
Reference in new issue
Block a user