From 7e17691af42782150b8ccdcb8f1371372394720e Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sat, 15 Aug 2026 17:01:41 -0700 Subject: [PATCH] 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 () suppress; lowercase dictionary words block. Pinned in both directions. --- lib/redact-patterns.ts | 10 +++++++++- test/redact-engine.test.ts | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/redact-patterns.ts b/lib/redact-patterns.ts index 2870c888f..96979db07 100644 --- a/lib/redact-patterns.ts +++ b/lib/redact-patterns.ts @@ -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[] = [ diff --git a/test/redact-engine.test.ts b/test/redact-engine.test.ts index 1f6a0a00c..dd6da49a1 100644 --- a/test/redact-engine.test.ts +++ b/test/redact-engine.test.ts @@ -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:@host/db")).not.toContain("db.url_with_password"); }); test("all HIGH patterns block (exit 3)", () => {