mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 15:31:13 +00:00
fix(models): reject oversized piped auth input (#109800)
readPipedStdin accumulated piped stdin without a size limit, letting `models auth paste-token` and `paste-api-key` buffer arbitrarily large input before any validation. Add a 1 MiB cap matching the existing Matrix recovery-key and config-patch stdin limits, and reject oversized input at the stream boundary.
This commit is contained in:
@@ -1473,6 +1473,21 @@ describe("modelsAuthLoginCommand", () => {
|
||||
expect(mocks.updateConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects oversized piped auth input before buffering it", async () => {
|
||||
const runtime = createRuntime();
|
||||
restoreStdin?.();
|
||||
const oversized = "x".repeat(1024 * 1024 + 1);
|
||||
restoreStdin = withPipedStdin(oversized);
|
||||
|
||||
await expect(modelsAuthPasteApiKeyCommand({ provider: "openai" }, runtime)).rejects.toThrow(
|
||||
"Piped auth input exceeds 1048576 bytes.",
|
||||
);
|
||||
|
||||
expect(mocks.clackPassword).not.toHaveBeenCalled();
|
||||
expect(mocks.upsertAuthProfileWithLock).not.toHaveBeenCalled();
|
||||
expect(mocks.updateConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("writes pasted API keys to the requested agent store", async () => {
|
||||
const runtime = createRuntime();
|
||||
useCoderAgentConfig();
|
||||
|
||||
@@ -130,13 +130,20 @@ const password = async (params: Parameters<typeof clackPassword>[0]) =>
|
||||
const select = async <T>(params: Parameters<typeof clackSelect<T>>[0]) =>
|
||||
guardCancel(await clackSelect(styleSelectParams(params)));
|
||||
|
||||
const MODELS_AUTH_STDIN_MAX_BYTES = 1024 * 1024;
|
||||
|
||||
async function readPipedStdin(): Promise<string> {
|
||||
process.stdin.setEncoding("utf8");
|
||||
let input = "";
|
||||
const chunks: Buffer[] = [];
|
||||
let totalBytes = 0;
|
||||
for await (const chunk of process.stdin) {
|
||||
input += String(chunk);
|
||||
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
||||
totalBytes += buffer.byteLength;
|
||||
if (totalBytes > MODELS_AUTH_STDIN_MAX_BYTES) {
|
||||
throw new Error(`Piped auth input exceeds ${MODELS_AUTH_STDIN_MAX_BYTES} bytes.`);
|
||||
}
|
||||
chunks.push(buffer);
|
||||
}
|
||||
return input;
|
||||
return Buffer.concat(chunks, totalBytes).toString("utf8");
|
||||
}
|
||||
|
||||
async function readPastedSecret(params: {
|
||||
|
||||
Reference in New Issue
Block a user