mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-19 00:00:13 +02:00
fix(redact): reject malformed --max-bytes instead of silently disabling the size guard (#1824)
The oversize check is designed to fail CLOSED, but a malformed --max-bytes turned
it fail-OPEN. bin/gstack-redact did parseInt(maxBytes,10) and passed it straight
through; parseInt("foo") is NaN. The engine guarded with `opts.maxBytes ?? DEFAULT`,
and ?? does not catch NaN, so `byteLen > NaN` was always false and the fail-closed
block never fired. A negative value made `byteLen > -5` always true, blocking
everything.
Two layers:
- bin/gstack-redact validates the RAW string (parseInt accepts "123abc"->123,
"1.5"->1): require /^\d+$/ and > 0, else exit 1 with a clear message.
- lib/redact-engine.ts hardens the fallback to Number.isFinite && > 0 else the
default cap — a guardrail so the engine never silently runs uncapped even if a
bad value reaches it directly.
Tests: NaN and negative both fall back to the default cap (oversize still blocks);
CLI rejects garbage/negative with exit 1.
Reported by @jbetala7.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -269,6 +269,27 @@ describe("oversize fails CLOSED", () => {
|
||||
expect(r.findings[0].id).toBe("engine.input_too_large");
|
||||
expect(exitCodeFor(r)).toBe(3);
|
||||
});
|
||||
|
||||
// #1824: a malformed --max-bytes used to reach the engine as NaN. `byteLen >
|
||||
// NaN` is always false, silently disabling the fail-closed guard. The engine
|
||||
// guardrail must fall back to the default cap for any non-finite / <= 0 value.
|
||||
test("NaN maxBytes falls back to the default cap (does NOT disable the guard)", () => {
|
||||
const big = "a".repeat(2 * 1024 * 1024); // > 1 MiB default cap
|
||||
const r = scan(big, { maxBytes: NaN });
|
||||
expect(r.oversize).toBe(true);
|
||||
expect(r.findings[0].id).toBe("engine.input_too_large");
|
||||
expect(exitCodeFor(r)).toBe(3);
|
||||
});
|
||||
|
||||
test("negative / zero maxBytes falls back to the default cap", () => {
|
||||
// negative would make `byteLen > -5` always true (block everything);
|
||||
// the guardrail normalizes it to the default instead.
|
||||
const small = "ok";
|
||||
expect(scan(small, { maxBytes: -5 }).oversize).toBeFalsy();
|
||||
expect(scan(small, { maxBytes: 0 }).oversize).toBeFalsy();
|
||||
const big = "a".repeat(2 * 1024 * 1024);
|
||||
expect(scan(big, { maxBytes: -5 }).oversize).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("validators", () => {
|
||||
|
||||
Reference in New Issue
Block a user