fix(observability): extend the redaction denylist with passphrase, otp, recovery, dsn

The wide-event `received_shape_excerpt` surface walks every body key
through `SENSITIVE_KEY_PATTERNS` before the eventual JSON.stringify.
The original set covered passwords, tokens, secrets, API keys, the
Authorization header, CSRF state, and nonces. Four additions worth
keeping out of observability sinks:

- `/passphrase/i` — backup-encryption passphrases (off-host backups
  use one) and any future user-facing recovery-phrase flows.
- `/otp/i` — TOTP / email-OTP one-time codes for future second-factor
  surfaces.
- `/recovery/i` — passkey-recovery codes and account-recovery flows.
- `/dsn/i` — Glitchtip / Sentry-style DSNs are `https://<key>@host`
  shapes where the key is auth material; today they enter the system
  via admin settings but a future debug surface might quote one back
  in a body excerpt.

Test pins the four new patterns alongside the existing required set,
and a positive-redaction case covers all four in one shot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-27 00:05:05 +02:00
1 parent 4b4fb7aaf8
commit 2d5b4cfac1
2 files changed
+30

No files matched your search

@@ -115,16 +115,37 @@ describe("redactSensitiveFields", () => {
// one of the documented patterns.
const required = [
"password",
"passphrase",
"token",
"secret",
"apikey",
"authorization",
"csrfstate",
"nonce",
"otp",
"recoveryCode",
"glitchtipDsn",
];
for (const key of required) {
const matched = SENSITIVE_KEY_PATTERNS.some((re) => re.test(key));
expect(matched, `pattern set should match ${key}`).toBe(true);
}
});
it("redacts the credential-adjacent additions (passphrase / otp / recovery / dsn)", () => {
const body = {
backupPassphrase: "correct horse battery staple",
emailOtp: "123456",
recoveryCode: "abcd-efgh-ijkl",
glitchtipDsn: "https://abc@glitchtip.example/1",
benignField: "kept",
};
expect(redactSensitiveFields(body)).toEqual({
backupPassphrase: "[redacted]",
emailOtp: "[redacted]",
recoveryCode: "[redacted]",
glitchtipDsn: "[redacted]",
benignField: "kept",
});
});
});
+9
View File
@@ -26,6 +26,7 @@
export const SENSITIVE_KEY_PATTERNS: readonly RegExp[] = [
/password/i,
/passphrase/i,
/token/i,
/secret/i,
/apikey/i,
@@ -34,6 +35,14 @@ export const SENSITIVE_KEY_PATTERNS: readonly RegExp[] = [
/csrfstate/i,
/csrf[_-]state/i,
/nonce/i,
// Credential-adjacent keys that aren't already covered by the broader
// `token` / `secret` patterns. TOTP / email-OTP one-time codes,
// account-recovery codes, and the observability DSNs that double as
// auth (Glitchtip / Sentry-style `https://<key>@host`) all carry
// material worth keeping out of wide-event excerpts.
/otp/i,
/recovery/i,
/dsn/i,
];
const REDACTED = "[redacted]";