fix(redact): lowercase 'password'/'pass' at the URL-password position blocks

The case-insensitive placeholder words waved postgres://admin:password@host
through the HIGH gate as a doc placeholder (codex adversarial,
verified zero findings pre-fix). URL-password position is now stricter
than generic placeholder detection: ALL-CAPS doc convention
(USER:PASSWORD), ${identifier} interpolations, bare $UPPER_SNAKE, and
structural shapes (<your-password>) suppress; lowercase dictionary
words block. Pinned in both directions.
This commit is contained in:
Garry Tan 2026-08-15 17:01:41 -07:00
parent 1e35386c54
commit 7e17691af4
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
2 changed files with 17 additions and 1 deletions

View File

@ -267,7 +267,15 @@ const INTERPOLATED_PASSWORD_RE = /^(\$\{[A-Za-z_][A-Za-z0-9_]*\}|\$[A-Z_][A-Z0-9
function urlPasswordIsPlaceholder(span: string): boolean {
const m = span.match(/:\/\/[^:]+:([^@]+)@/);
const pw = m?.[1] ?? "";
return pw === "" || isPlaceholderSpan(pw) || INTERPOLATED_PASSWORD_RE.test(pw);
if (pw === "") return true;
if (INTERPOLATED_PASSWORD_RE.test(pw)) return true;
// URL-password position is STRICTER than generic placeholder detection.
// Doc-comment convention writes placeholders in ALL CAPS
// (postgres://USER:PASSWORD@host); a lowercase `password` or `pass` at
// this position is a real (terrible) credential and must block — the
// case-insensitive isPlaceholderSpan words would wave it through.
if (/^[A-Z][A-Z0-9_]*$/.test(pw)) return true;
return PLACEHOLDER_STRUCTURAL.some((re) => re.test(pw));
}
export const PATTERNS: RedactPattern[] = [

View File

@ -121,6 +121,14 @@ describe("HIGH credential patterns", () => {
expect(ids("postgres://admin:$" + "hun" + "ter2@db.internal/app")).toContain("db.url_with_password");
// Mismatched brace is not an interpolation either.
expect(ids("postgres://admin:${dbPass@db.internal/app")).toContain("db.url_with_password");
// A LOWERCASE literal 'password'/'pass' at the URL-password position is a
// real (terrible) credential, not a doc placeholder — only the ALL-CAPS
// doc convention (USER:PASSWORD) is suppressed. Assembled at runtime so
// this file's own bytes never carry a live credential shape.
expect(ids("postgres://admin:" + "pass" + "word@10.0.0.5/app")).toContain("db.url_with_password");
expect(ids("https://root:" + "pa" + "ss@127.0.0.1/")).toContain("creds.basic_auth_url");
// Structural placeholders still suppress at the URL position.
expect(ids("postgres://user:<your-password>@host/db")).not.toContain("db.url_with_password");
});
test("all HIGH patterns block (exit 3)", () => {