From ec201d3a1dc49e06defdfad324891c92d0daabb9 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:40:01 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20CodeRabbit=20CI=20Fix:=20Fix=20f?= =?UTF-8?q?ailing=20GitHub=20Actions=20Docker=20and=20CI=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/check-client-bundle-secrets.mjs | 15 ++++++++++----- tests/client-secret-surface.test.ts | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/scripts/check-client-bundle-secrets.mjs b/scripts/check-client-bundle-secrets.mjs index 9319a103f..a007ab333 100644 --- a/scripts/check-client-bundle-secrets.mjs +++ b/scripts/check-client-bundle-secrets.mjs @@ -11,9 +11,12 @@ const forbiddenMarkers = [ "OPENAI_ORG_ID", "OPENAI_PROJECT_ID", "RAG_QUERY_HASH_SECRET", - "sb_secret_", - "sk-proj-", - "sk-svcacct-", + // Match an actual key value (prefix + key body), not a bare prefix-check + // string literal. @supabase/supabase-js ships `key.startsWith('sb_secret_')` + // client-side as of 2.110.x, which would otherwise be a false positive here. + /sb_secret_[A-Za-z0-9]/, + /sk-proj-[A-Za-z0-9]/, + /sk-svcacct-[A-Za-z0-9]/, ]; function textFiles(root) { @@ -47,9 +50,11 @@ const offenders = new Map(); for (const file of [...textFiles(publicRoot), ...textFiles(clientBuildRoot)]) { const content = readFileSync(file, "utf8"); for (const marker of forbiddenMarkers) { - if (content.includes(marker)) { + const matched = marker instanceof RegExp ? marker.test(content) : content.includes(marker); + if (matched) { + const markerLabel = marker instanceof RegExp ? marker.source : marker; const relativePath = relative(projectRoot, file).replaceAll("\\", "/"); - offenders.set(`${relativePath}\0${marker}`, { marker, relativePath }); + offenders.set(`${relativePath}\0${markerLabel}`, { marker: markerLabel, relativePath }); } } } diff --git a/tests/client-secret-surface.test.ts b/tests/client-secret-surface.test.ts index 9db8dcf02..8f911214c 100644 --- a/tests/client-secret-surface.test.ts +++ b/tests/client-secret-surface.test.ts @@ -169,6 +169,23 @@ describe("client environment isolation", () => { expect(publicResult.status).toBe(1); expect(publicResult.stderr).toContain("public/unsafe.txt"); expect(publicResult.stderr).toContain("SUPABASE_SERVICE_ROLE_KEY"); + + rmSync(join(fixtureRoot, "public", "unsafe.txt")); + // @supabase/supabase-js ships a bare `key.startsWith('sb_secret_')` prefix + // check client-side; that literal alone must not trip the scanner. + writeFileSync( + join(staticRoot, "sdk-prefix-check.js"), + "const isNewApiKey = (key) => key.startsWith(\"sb_publishable_\") || key.startsWith(\"sb_secret_\");", + "utf8", + ); + const prefixOnlyResult = spawnSync(process.execPath, [scannerPath], { cwd: fixtureRoot, encoding: "utf8" }); + expect(prefixOnlyResult.status).toBe(0); + + rmSync(join(staticRoot, "sdk-prefix-check.js")); + writeFileSync(join(staticRoot, "leaked-key.js"), "const key = 'sb_secret_abc123DEF456';", "utf8"); + const leakedKeyResult = spawnSync(process.execPath, [scannerPath], { cwd: fixtureRoot, encoding: "utf8" }); + expect(leakedKeyResult.status).toBe(1); + expect(leakedKeyResult.stderr).toContain(".next/static/leaked-key.js"); } finally { rmSync(fixtureRoot, { recursive: true, force: true }); }