🔐 fix: Anchor Secret Regexes at Word Boundaries to Prevent Over-Redaction

Removing the `^` anchor in commit e288f7fd let the OpenAI-key regex match
anywhere in the line — including inside ordinary words like `task-runner`
or `mask-value`, where `sk-` appears mid-word. Non-secret text was being
rewritten to `task-[REDACTED]`, hiding real log content from operators.

- Anchor every sensitive-key pattern with `\b` so matches only fire at
  word boundaries.
- Constrain the OpenAI-key body to the documented charset
  (`[a-zA-Z0-9_-]+`) instead of the broader "not whitespace or quote"
  character class.
- Add `&` to the `key=` exclusion so a query-string value stops at the
  next parameter separator.
- Regression tests covering both the over-redaction cases (`task-runner`,
  `monkey=10`) and the intended redactions still firing.

Reviewed-by: Codex (P2 finding on PR #12737, commit c09d293d).
This commit is contained in:
Danny Avila 2026-04-18 11:31:00 -04:00
parent c09d293d47
commit fdb6b36179
2 changed files with 22 additions and 4 deletions

View file

@ -136,6 +136,21 @@ describe('redactMessage', () => {
expect(redactMessage('')).toBe('');
expect(redactMessage(undefined)).toBe('');
});
it('does not redact ordinary words that contain "sk-" inside them', () => {
expect(redactMessage('task-runner failed')).toBe('task-runner failed');
expect(redactMessage('mask-value computed')).toBe('mask-value computed');
expect(redactMessage('desk-lamp is on')).toBe('desk-lamp is on');
});
it('does not redact words that contain "key=" inside them', () => {
expect(redactMessage('monkey=10 bananas')).toBe('monkey=10 bananas');
});
it('still redacts standalone sk- keys at word boundaries', () => {
expect(redactMessage('token: sk-abc123def')).toBe('token: sk-[REDACTED]');
expect(redactMessage('"sk-abc123def"')).toBe('"sk-[REDACTED]"');
});
});
describe('debugTraverse', () => {

View file

@ -8,10 +8,13 @@ const CONSOLE_JSON_STRING_LENGTH = parseInt(process.env.CONSOLE_JSON_STRING_LENG
const DEBUG_MESSAGE_LENGTH = parseInt(process.env.DEBUG_MESSAGE_LENGTH) || 150;
const sensitiveKeys = [
/(sk-)[^\s"']+/g, // OpenAI API key pattern (also catches keys embedded in JSON/quoted strings)
/(Bearer )[^\s"']+/g, // Header: Bearer token pattern
/(api-key:? )[^\s"']+/g, // Header: API key pattern
/(key=)[^\s"']+/g, // URL query param: sensitive key pattern (Google)
// OpenAI API key: `sk-` at a word boundary, followed by the documented
// charset for keys. `\b` keeps `task-runner`, `mask-value`, etc. from
// being mis-redacted.
/\b(sk-)[a-zA-Z0-9_-]+/g,
/\b(Bearer )[^\s"']+/g, // Header: Bearer token pattern
/\b(api-key:? )[^\s"']+/g, // Header: API key pattern
/\b(key=)[^\s"'&]+/g, // URL query param: sensitive key pattern (Google)
];
/**