From fb3be30ed4b527ae81137c705760b2b050ab5358 Mon Sep 17 00:00:00 2001 From: bohdansolovie Date: Sun, 5 Jul 2026 03:12:35 +0200 Subject: [PATCH] feat(enrichment): detect fal.ai and Weights & Biases API keys in secret-scan Add high-confidence rules for fal_sk_ (fal.ai) and wandb_v1_ (77-char body) with truncation and identifier-continuation regression tests. Co-authored-by: Cursor --- .../src/analyzers/secret-scan.ts | 12 +++++++ review-enrichment/test/secret-scan.test.ts | 36 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/review-enrichment/src/analyzers/secret-scan.ts b/review-enrichment/src/analyzers/secret-scan.ts index 582d7d19a9..3cbb9f8ee2 100644 --- a/review-enrichment/src/analyzers/secret-scan.ts +++ b/review-enrichment/src/analyzers/secret-scan.ts @@ -259,6 +259,18 @@ const RULES: Rule[] = [ re: /\b(?:ak|as)-[A-Za-z0-9]{20,}(?![A-Za-z0-9_-])/, confidence: "high", }, + { + // fal.ai API key: `fal_sk_` + base62 body (reject hyphen-continued identifiers). + kind: "fal_api_key", + re: /\bfal_sk_[A-Za-z0-9]{20,}(?![A-Za-z0-9_-])/, + confidence: "high", + }, + { + // Weights & Biases API key: `wandb_v1_` + 77 base62/underscore chars. + kind: "wandb_api_key", + re: /\bwandb_v1_[A-Za-z0-9_]{77}(?![A-Za-z0-9_])/, + confidence: "high", + }, { // Google OAuth 2.0 client secret: `GOCSPX-` + 28 base64url chars. kind: "google_oauth_client_secret", diff --git a/review-enrichment/test/secret-scan.test.ts b/review-enrichment/test/secret-scan.test.ts index 97d17387c3..a70ac67853 100644 --- a/review-enrichment/test/secret-scan.test.ts +++ b/review-enrichment/test/secret-scan.test.ts @@ -679,6 +679,42 @@ test("scanPatch does not flag truncated Browserbase/Modal tokens or identifier c ); }); +test("scanPatch flags fal.ai and Weights & Biases API keys with high confidence", () => { + const fakeFalKey = "fal_sk_" + "a".repeat(20); + const falFindings = scanPatch("src/config.ts", hunk([`const fal = "${fakeFalKey}";`])); + assert.equal(falFindings.length, 1); + assert.equal(falFindings[0].kind, "fal_api_key"); + assert.equal(falFindings[0].confidence, "high"); + + const fakeWandbKey = "wandb_v1_" + "a".repeat(77); + const wandbFindings = scanPatch("src/config.ts", hunk([`const wandb = "${fakeWandbKey}";`])); + assert.equal(wandbFindings.length, 1); + assert.equal(wandbFindings[0].kind, "wandb_api_key"); + assert.equal(wandbFindings[0].confidence, "high"); +}); + +test("scanPatch does not flag truncated fal/W&B keys or identifier continuation", () => { + assert.equal(scanPatch("src/config.ts", hunk([`const fal = "fal_sk_${"a".repeat(19)}";`])).length, 0); + assert.equal( + scanPatch("src/config.ts", hunk([`const fal = "fal_sk_${"a".repeat(20)}_suffix";`])).some((f) => f.kind === "fal_api_key"), + false, + ); + assert.equal( + scanPatch("src/config.ts", hunk([`const fal = "fal_sk_${"a".repeat(20)}-suffix";`])).some((f) => f.kind === "fal_api_key"), + false, + ); + + assert.equal(scanPatch("src/config.ts", hunk([`const wandb = "wandb_v1_${"a".repeat(76)}";`])).length, 0); + assert.equal( + scanPatch("src/config.ts", hunk([`const wandb = "wandb_v1_${"a".repeat(77)}X";`])).some((f) => f.kind === "wandb_api_key"), + false, + ); + assert.equal( + scanPatch("src/config.ts", hunk([`const wandb = "wandb_v1_${"a".repeat(77)}_suffix";`])).some((f) => f.kind === "wandb_api_key"), + false, + ); +}); + test("scanPatch flags additional high-confidence SaaS/cloud/CI credential formats", () => { const cases = [ ["google_oauth_client_secret", "GOCSPX-" + b62(28)],