mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 10:52:17 +03:00
Validado sobre o tip de `release/v3.8.51` depois de reconciliar com o #12620, que entrou primeiro nesta mesma sessão e ataca a mesma classe de problema por outra arquitetura. **A colisão e como foi resolvida.** O #12620 consertou o GHSA-qv45-56jc-4wmj adicionando `RAW_CREDENTIAL_PATTERNS` a `error.ts` e importando-os em `upstreamErrorPassthrough.ts`. Este PR resolve o mesmo problema quebrando `error.ts` em `errorSanitization.ts` + `errorPathRedaction.ts`. Mantive a divisão em módulos deste PR, porque ao comparar os dois vocabulários o dele já era mais amplo: o `STRONG_CREDENTIAL_TOKEN` daqui cobre `sk-`/`sk_` **com lookbehind e uma variante para a forma embutida** (que pega `sk-proj-…`), mais Slack `xox-`, AWS `AKIA`/`ASIA`, `github_pat_`/`ghp_`/`glpat-` e JWT de três segmentos. A única forma que o #12620 carregava e este conjunto não tinha era a chave do Google (`AIza…`) — adicionada aqui, com o mesmo quantificador limitado que os irmãos usam (AGENTS.md → PII §1, já que isso roda sobre corpos upstream não confiáveis). **A verificação não foi por inspeção.** Rodei as suítes do próprio #12620 contra esta estrutura: **48/48** em `error-sanitizer-sk-key-qv45`, `bifrost-relay-response-leak-9m72`, `search-baseurl-client-override-3f8g` e `search-baseurl-ssrf-guard` — incluindo a asserção anti-drift daquela suíte, que é o oráculo certo aqui: *para todo corpo que a camada de passthrough recusa como vazante, o sanitizador de fallback não pode devolvê-lo intacto*. Ela passa, então a propriedade de segurança dos três GHSAs sobrevive à troca de arquitetura. Os 21 arquivos de teste deste PR: **259/259**. `typecheck:core` limpo.
80 lines
3.0 KiB
TypeScript
80 lines
3.0 KiB
TypeScript
/** Pure credential signatures shared by guardrails and public error sanitization. */
|
|
export interface CredentialPattern {
|
|
name: string;
|
|
regex: RegExp;
|
|
replacement: string;
|
|
}
|
|
|
|
export const CREDENTIAL_PATTERNS: CredentialPattern[] = [
|
|
{ name: "openai_proj", regex: /sk-proj-[A-Za-z0-9_-]{20,}/g, replacement: "[REDACTED:openai]" },
|
|
{ name: "openai", regex: /\bsk-[A-Za-z0-9]{48}\b/g, replacement: "[REDACTED:openai]" },
|
|
{
|
|
name: "anthropic",
|
|
regex: /sk-ant-api[0-9]?-[A-Za-z0-9_-]{20,}/g,
|
|
replacement: "[REDACTED:anthropic]",
|
|
},
|
|
{
|
|
name: "anthropic_alt",
|
|
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]" },
|
|
{ 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]" },
|
|
{ name: "slack", regex: /xox[bpoa]-[A-Za-z0-9-]{10,}/g, replacement: "[REDACTED:slack]" },
|
|
{ name: "linear", regex: /lin_api_[A-Za-z0-9]{40}/g, replacement: "[REDACTED:linear]" },
|
|
{ name: "notion", regex: /secret_[A-Za-z0-9]{43}/g, replacement: "[REDACTED:notion]" },
|
|
{ name: "npm", regex: /npm_[A-Za-z0-9]{36}/g, replacement: "[REDACTED:npm]" },
|
|
{
|
|
name: "postman",
|
|
regex: /PMAK-[a-f0-9]{8}-[a-f0-9]{32}/g,
|
|
replacement: "[REDACTED:postman]",
|
|
},
|
|
{
|
|
name: "discord",
|
|
regex: /\b[MN][A-Za-z0-9]{23}\.[A-Za-z0-9]{6}\.[A-Za-z0-9]{27}\b/g,
|
|
replacement: "[REDACTED:discord]",
|
|
},
|
|
{
|
|
name: "stripe",
|
|
regex: /(?:sk|rk)_(?:live|test)_[0-9a-zA-Z]{24,}/g,
|
|
replacement: "[REDACTED:stripe]",
|
|
},
|
|
{
|
|
name: "square",
|
|
regex: /sq0(?:atp-[0-9A-Za-z_-]{22}|csp-[0-9A-Za-z_-]{43})/g,
|
|
replacement: "[REDACTED:square]",
|
|
},
|
|
{ name: "aws_access_key", regex: /AKIA[0-9A-Z]{16}/g, replacement: "[REDACTED:aws]" },
|
|
{ name: "twilio", regex: /\bSK[0-9a-fA-F]{32}\b/g, replacement: "[REDACTED:twilio]" },
|
|
{
|
|
name: "sendgrid",
|
|
regex: /SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}/g,
|
|
replacement: "[REDACTED:sendgrid]",
|
|
},
|
|
{ name: "mailgun", regex: /key-[a-f0-9]{32}/g, replacement: "[REDACTED:mailgun]" },
|
|
{
|
|
name: "private_key",
|
|
regex:
|
|
/-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY-----/g,
|
|
replacement: "[REDACTED:private_key]",
|
|
},
|
|
{
|
|
name: "jwt",
|
|
regex: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
|
|
replacement: "[REDACTED:jwt]",
|
|
},
|
|
{
|
|
name: "connection_string",
|
|
regex: /(?:mongodb(?:\+srv)?|postgres(?:ql)?|mysql|redis|amqp):\/\/[^:/@\s"']+:[^:/@\s"']+@/g,
|
|
replacement: "[REDACTED:connection_string]",
|
|
},
|
|
{
|
|
name: "auth_header",
|
|
regex:
|
|
/((?:["\x27]?(?:Authorization|x-api-key|api-key|apikey)["\x27]?\s*[:=]\s*["\x27]?)(?:(?:Bearer|Basic|Token)\s+)?)[A-Za-z0-9._~+/=-]{10,}/gi,
|
|
replacement: "$1[REDACTED:auth_header]",
|
|
},
|
|
];
|