fix: harden runtime config snapshot publication
This commit is contained in:
@@ -306,6 +306,12 @@ export class ThtRunner {
|
||||
return new Promise((resolve) => {
|
||||
const env: NodeJS.ProcessEnv = { ...process.env };
|
||||
delete env.THT_DATA_ROOT;
|
||||
// Handoff variables are backend-owned capabilities, never inherited from an
|
||||
// operator shell or forwarded request environment.
|
||||
delete env.THT_RUNTIME_CONFIG_MANIFEST_SHA256;
|
||||
delete env.THT_CONFIG_FD;
|
||||
delete env.THT_CONFIG_MANIFEST_FD;
|
||||
delete env.THT_CONFIG_MANIFEST_SHA256;
|
||||
clearPrincipalEnvironment(env);
|
||||
if (this.cfg.dataRoot !== undefined) env.THT_DATA_ROOT = this.cfg.dataRoot;
|
||||
if (this.principal) Object.assign(env, principalEnvironment(this.principal));
|
||||
@@ -321,41 +327,27 @@ export class ThtRunner {
|
||||
env.THT_SSL_CA = ca;
|
||||
}
|
||||
let snapshotFd: number | undefined;
|
||||
let canonicalFd: number | undefined;
|
||||
let manifestFd: number | undefined;
|
||||
let ch;
|
||||
try {
|
||||
snapshotFd = workspaceConfigPath && this.runtimeSnapshots.has(workspaceConfigPath)
|
||||
? this.openTrustedRuntimeSnapshot(workspaceConfigPath) : undefined;
|
||||
const lease = workspaceConfigPath ? this.runtimeLeases.get(workspaceConfigPath) : undefined;
|
||||
// Registry leases retain the verified config bytes in fd 3 and the separately
|
||||
// published manifest in fd 4. The argv remains the canonical -c pathname for
|
||||
// diagnostics/compatibility; the harness never trusts that pathname for bytes.
|
||||
canonicalFd = snapshotFd === undefined && lease
|
||||
? openSync(lease.path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW) : undefined;
|
||||
manifestFd = lease
|
||||
? openSync(lease.manifestPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW) : undefined;
|
||||
if (lease) {
|
||||
env.THT_CONFIG_FD = "3";
|
||||
env.THT_CONFIG_MANIFEST_FD = "4";
|
||||
env.THT_CONFIG_MANIFEST_SHA256 = lease.manifestSha256;
|
||||
}
|
||||
const handoffFd = snapshotFd ?? canonicalFd;
|
||||
// Runtime leases use the canonical path plus an authenticated manifest digest.
|
||||
// FD 3/4 remain reserved for the maintenance writer/root ABI.
|
||||
if (lease) env.THT_RUNTIME_CONFIG_MANIFEST_SHA256 = lease.manifestSha256;
|
||||
ch = spawn(
|
||||
this.cfg.thtBin,
|
||||
snapshotFd === undefined ? this.buildArgv(args, workspaceConfigPath) : [...args, "-c", "/dev/fd/3"],
|
||||
{
|
||||
cwd: this.cfg.harnessDir,
|
||||
env,
|
||||
...(handoffFd === undefined ? {} : {
|
||||
stdio: ["ignore", "pipe", "pipe", handoffFd, ...(manifestFd === undefined ? [] : [manifestFd])],
|
||||
...(snapshotFd === undefined ? {} : {
|
||||
stdio: ["ignore", "pipe", "pipe", snapshotFd],
|
||||
}),
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
if (snapshotFd !== undefined) closeSync(snapshotFd);
|
||||
if (canonicalFd !== undefined) closeSync(canonicalFd);
|
||||
if (manifestFd !== undefined) closeSync(manifestFd);
|
||||
}
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
Reference in New Issue
Block a user