Skip to main content

No service-role/secret keys exposed via PUBLIC_ prefix

ab-002568 · project-snapshot.secrets.no-sensitive-vars-public-prefixed
Severity: highactive

Why it matters

A variable name like NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY is a direct contradiction in terms — the NEXT_PUBLIC_ prefix tells the bundler to inline the value into every client bundle, and a service-role key grants RLS-bypassing database access. Shipping one to the browser gives any visitor full admin privileges against the database, including reading other users' rows, writing arbitrary data, and deleting tables. This specific combination shows up constantly in AI-generated Supabase starters because the tool sees SUPABASE_ env vars in docs and reaches for the public prefix out of pattern-matching habit, not understanding the access-tier distinction between anon and service-role keys. The variable name alone is enough signal to flag — intent doesn't matter when the prefix dictates build-time behavior.

Severity rationale

High because the naming pattern guarantees client-bundle exposure on the next deploy, and a leaked service-role key typically means full database compromise — one tier below critical only because the sensitive value may not actually be populated yet.

Remediation

Rename to drop the public prefix, treat the credential as compromised, rotate it. For Supabase: use the anon key client-side (already public-safe) and service-role only in server code.

Deeper remediation guidance and cross-reference coverage for this check lives in the security-hardening Pro audit — run that after applying this fix for a more exhaustive pass on the same topic.

Detection

  • ID: project-snapshot.secrets.no-sensitive-vars-public-prefixed
  • Severity: high
  • What to look for: Search for env var names that combine the framework's public prefix with sensitive substrings. Patterns: NEXT_PUBLIC_*SECRET*, NEXT_PUBLIC_*SERVICE_ROLE*, NEXT_PUBLIC_*PRIVATE*, NEXT_PUBLIC_*ADMIN*, VITE_*SECRET*, VITE_*SERVICE_ROLE*, PUBLIC_*SECRET*, etc. Count matches across .env.example, .env.sample, source files, and config files.
  • Pass criteria: Zero env var declarations or usages match the dangerous public+sensitive combination.
  • Fail criteria: At least one match. Common offender: NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY shipped in client bundles.
  • Skip (N/A) when: No client-side framework detected.
  • Do NOT pass when: Even one variable name matches — public prefix + sensitive substring is a red flag regardless of intent.
  • Report even on pass: "Scanned env declarations and source for public-prefixed sensitive vars: 0 matches."
  • Detail on fail: "Found NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY in .env.example — service role key would ship to the client bundle."
  • Remediation: Rename to drop the public prefix, treat the credential as compromised, rotate it. For Supabase: use the anon key client-side (already public-safe) and service-role only in server code.

Taxons

History