feat(redact): add Groq, Tavily and Notion API key patterns

This commit is contained in:
schienbiz
2026-08-31 20:52:28 +00:00
committed by Garry Tan
parent 4dc3516bcc
commit b77c1923c8
2 changed files with 37 additions and 0 deletions
+27
View File
@@ -438,6 +438,33 @@ export const PATTERNS: RedactPattern[] = [
// gstack drives glab first-class — these were a coverage gap (#1946).
regex: /\b(gl(?:pat|ptt|dt)-[A-Za-z0-9_-]{20,})\b/,
},
{
id: "groq.key",
tier: "HIGH",
category: "secret",
description: "Groq API key",
regex: /\b(gsk_[A-Za-z0-9]{20,})\b/,
},
{
id: "tavily.key",
tier: "HIGH",
category: "secret",
description: "Tavily API key (incl. tvly-dev-/tvly-prod-)",
// Explicit environment infixes rather than a globally-optional segment,
// which would also match separator-less tvly-devabc… (same reasoning as
// openai.key above).
regex: /\b(tvly-(?:dev-|prod-)?[A-Za-z0-9]{16,})\b/,
},
{
id: "notion.token",
tier: "HIGH",
category: "secret",
description: "Notion integration token (ntn_ current, secret_ legacy)",
// Two explicit shapes. The legacy `secret_` form keeps a high {40,} floor
// because the prefix is an ordinary English word — the length is what makes
// it a credential rather than prose.
regex: /\b(ntn_[A-Za-z0-9]{40,}|secret_[A-Za-z0-9]{40,})\b/,
},
{
id: "huggingface.token",
tier: "HIGH",
+10
View File
@@ -48,6 +48,11 @@ describe("HIGH credential patterns", () => {
["gitlab.token", "remote: glpat-" + "Ab12Cd34Ef56Gh78Ij90"],
["gitlab.token", "trigger glptt-" + "a1b2c3d4e5f6a7b8c9d0e1f2"],
["gitlab.token", "deploy gldt-" + "Zy98Xw76Vu54Ts32Rq10"],
["groq.key", "gsk_" + "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMn"],
["tavily.key", "tvly-" + "AbCdEfGhIjKlMnOpQrStUvWx"],
["tavily.key", "tvly-dev-" + "AbCdEfGhIjKlMnOpQrStUvWx"],
["notion.token", "ntn_" + "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGh"],
["notion.token", "secret_" + "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGh"],
["huggingface.token", "hf_" + "AbCdEfGhIjKlMnOpQrStUvWxYz012345"],
["npm.token", "npm_" + "a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8"],
["digitalocean.token", "dop_v1_" + "0123456789abcdef".repeat(4)],
@@ -261,6 +266,11 @@ describe("#1946 pattern negatives (placeholders never fire)", () => {
test("short or placeholder shapes don't trip the new HIGH patterns", () => {
expect(ids("glpat-xxxx")).not.toContain("gitlab.token");
expect(ids("hf_token")).not.toContain("huggingface.token");
expect(ids("gsk_key")).not.toContain("groq.key");
expect(ids("tvly-key")).not.toContain("tavily.key");
expect(ids("ntn_token")).not.toContain("notion.token");
// `secret_` is an ordinary word; only the length makes it a credential.
expect(ids("secret_value")).not.toContain("notion.token");
expect(ids("npm_install")).not.toContain("npm.token");
expect(ids("dop_v1_short")).not.toContain("digitalocean.token");
// pem header WITHOUT the GCP JSON shape stays pem.private_key only.