From 89c42d36dfae70b6e15d4873b8f59d4523489ae2 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Tue, 8 Sep 2026 09:10:36 -0300 Subject: [PATCH] fix(security): redact AIza credentials of any length in error bodies (#12964) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vazamento de credencial em corpo de erro. `tests/unit/error-sanitizer-sk-key-qv45.test.ts` falhava no tip em 8ms: ``` AssertionError: Google key survived: Bad credentials for AIzaSyA1B2C3D4E5F6G7H8I9J0KaLbMcNdOeP ``` O padrão era `/AIza[0-9A-Za-z_-]{35}/` — comprimento **exato**. Uma chave Google padrão tem 39 caracteres e casa; qualquer credencial `AIza…` mais curta ou mais longa passava direto para o corpo do erro. Os dois lados divergiram na reconciliação de dois PRs do mesmo GHSA: o padrão com `{35}` veio do #12506, o teste anti-drift que cobra `/\\bAIza[A-Za-z0-9_-]{20,}/` veio do #12620. Está vermelho desde que os dois entraram em sequência. `{20,}` no lugar de `{35}`. Numa mensagem de erro, redigir demais uma string que apenas começa com `AIza` não custa nada; redigir de menos vaza credencial — o lado errado para errar é claro. Evidência: o arquivo vai de 7/9 para **9/9**. Bateria de sanitização com 538 testes: 533 passam, e as 5 restantes são pré-existentes no tip, não desta mudança (4 levam 21–25s por spawn de processo isolado sob carga; `tunnel-routes-error-sanitization` falha igual no tip puro, verificado). Nenhum teste foi enfraquecido — o padrão foi ampliado para satisfazer uma asserção que já existia. --- changelog.d/fixes/google-key-redaction-length.md | 1 + open-sse/utils/credentialPatterns.ts | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 changelog.d/fixes/google-key-redaction-length.md diff --git a/changelog.d/fixes/google-key-redaction-length.md b/changelog.d/fixes/google-key-redaction-length.md new file mode 100644 index 0000000000..e212604119 --- /dev/null +++ b/changelog.d/fixes/google-key-redaction-length.md @@ -0,0 +1 @@ +- Redact Google API keys of any length in error bodies: the pattern required exactly 39 characters, so shorter or longer `AIza…` credentials passed through unredacted. diff --git a/open-sse/utils/credentialPatterns.ts b/open-sse/utils/credentialPatterns.ts index 02784a4ae5..b9a2366d70 100644 --- a/open-sse/utils/credentialPatterns.ts +++ b/open-sse/utils/credentialPatterns.ts @@ -18,7 +18,13 @@ export const CREDENTIAL_PATTERNS: CredentialPattern[] = [ regex: /sk-ant-[A-Za-z0-9_-]{20,}/g, replacement: "[REDACTED:anthropic]", }, - { name: "google", regex: /AIza[0-9A-Za-z_-]{35}/g, replacement: "[REDACTED:google]" }, + // {20,} rather than the exact {35} of a standard 39-char Google API key. #12506 added + // this pattern with the exact length; #12620 landed the anti-drift test that asserts + // /\bAIza[A-Za-z0-9_-]{20,}/ must not survive. Anything shorter or longer than 39 was + // therefore passing straight through into error bodies. In an error message + // over-redacting a string that merely starts with AIza costs nothing; under-redacting + // one leaks a credential, so the loose bound is the correct side to err on. + { name: "google", regex: /AIza[0-9A-Za-z_-]{20,}/g, replacement: "[REDACTED:google]" }, { name: "huggingface", regex: /hf_[A-Za-z0-9]{34}/g, replacement: "[REDACTED:hf]" }, { name: "replicate", regex: /r8_[A-Za-z0-9]{37}/g, replacement: "[REDACTED:replicate]" }, { name: "github", regex: /gh[pousr]_[A-Za-z0-9]{36,}/g, replacement: "[REDACTED:github]" },