mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-07 18:42:25 +00:00
fix(e2e): bound secret resolver stdin
This commit is contained in:
@@ -45,6 +45,11 @@ const OUTPUT_CAPTURE_LIMIT_BYTES = readPositiveInt(
|
||||
4 * 1024 * 1024,
|
||||
"OPENCLAW_SECRET_PROOF_OUTPUT_BYTES",
|
||||
);
|
||||
const RESOLVER_STDIN_LIMIT_BYTES = readPositiveInt(
|
||||
process.env.OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES,
|
||||
1024 * 1024,
|
||||
"OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES",
|
||||
);
|
||||
const RESULTS_PATH =
|
||||
process.env.OPENCLAW_SECRET_PROOF_RESULTS_PATH?.trim() ||
|
||||
path.join(os.tmpdir(), `openclaw-secret-provider-e2e-results-${process.pid}.json`);
|
||||
@@ -596,15 +601,36 @@ if (!storePath) {
|
||||
console.error("missing PROOF_SECRET_STORE_PATH");
|
||||
process.exit(4);
|
||||
}
|
||||
const stdinLimitBytes = ${RESOLVER_STDIN_LIMIT_BYTES};
|
||||
|
||||
function readStdin() {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let body = "";
|
||||
let bytes = 0;
|
||||
let failed = false;
|
||||
const fail = (error) => {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
failed = true;
|
||||
reject(error);
|
||||
};
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", (chunk) => {
|
||||
bytes += Buffer.byteLength(chunk, "utf8");
|
||||
if (bytes > stdinLimitBytes) {
|
||||
fail(new Error(\`resolver stdin exceeded \${stdinLimitBytes} bytes\`));
|
||||
process.stdin.destroy();
|
||||
return;
|
||||
}
|
||||
body += chunk;
|
||||
});
|
||||
process.stdin.on("end", () => resolve(body));
|
||||
process.stdin.on("error", fail);
|
||||
process.stdin.on("end", () => {
|
||||
if (!failed) {
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1835,6 +1861,7 @@ export {
|
||||
runCommand,
|
||||
startGateway,
|
||||
waitForManagedGatewayStatus,
|
||||
writeProofPlugin,
|
||||
};
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
||||
|
||||
@@ -258,6 +258,7 @@ describe("secret provider integration proof harness", () => {
|
||||
["OPENCLAW_SECRET_PROOF_COMMAND_MS", "150ms"],
|
||||
["OPENCLAW_SECRET_PROOF_READY_MS", "0"],
|
||||
["OPENCLAW_SECRET_PROOF_OUTPUT_BYTES", "4mb"],
|
||||
["OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES", "4mb"],
|
||||
])("rejects malformed proof env limit %s=%s", async (name, value) => {
|
||||
const previous = process.env[name];
|
||||
process.env[name] = value;
|
||||
@@ -274,6 +275,48 @@ describe("secret provider integration proof harness", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("bounds generated resolver stdin before reading the secret store", async () => {
|
||||
const root = makeTempDir();
|
||||
const stateDir = path.join(root, "state");
|
||||
fs.mkdirSync(stateDir, { recursive: true });
|
||||
const storePath = path.join(stateDir, "proof-secret-store.json");
|
||||
fs.writeFileSync(
|
||||
storePath,
|
||||
`${JSON.stringify({ mode: "ok", calls: 0, values: { "proof/id": "ok" } }, null, 2)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
const previousLimit = process.env.OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES;
|
||||
process.env.OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES = "64";
|
||||
|
||||
try {
|
||||
const proof = await import(
|
||||
`${pathToFileURL(proofScriptPath).href}?case=resolver-stdin-${Date.now()}`
|
||||
);
|
||||
const plugin = proof.writeProofPlugin({ stateDir });
|
||||
const result = spawnSync(process.execPath, [plugin.resolverPath], {
|
||||
cwd: plugin.pluginRoot,
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
PROOF_SECRET_STORE_PATH: storePath,
|
||||
},
|
||||
input: JSON.stringify({ ids: ["proof/id"], padding: "x".repeat(512) }),
|
||||
timeout: 5_000,
|
||||
});
|
||||
|
||||
expect(result.error).toBeUndefined();
|
||||
expect(result.status).not.toBe(0);
|
||||
expect(`${result.stderr}${result.stdout}`).toContain("resolver stdin exceeded 64 bytes");
|
||||
expect(JSON.parse(fs.readFileSync(storePath, "utf8")).calls).toBe(0);
|
||||
} finally {
|
||||
if (previousLimit === undefined) {
|
||||
delete process.env.OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES;
|
||||
} else {
|
||||
process.env.OPENCLAW_SECRET_PROOF_RESOLVER_STDIN_BYTES = previousLimit;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("fails when proof temp cleanup cannot remove the root", async () => {
|
||||
const proof = await import(`${pathToFileURL(proofScriptPath).href}?case=cleanup-${Date.now()}`);
|
||||
const rmSync = vi.spyOn(fs, "rmSync").mockImplementation(() => {
|
||||
|
||||
Reference in New Issue
Block a user