Security
security/no-secrets-in-client-env
Secrets never use a client-exposed environment prefix (NEXT_PUBLIC_, VITE_, PUBLIC_, NUXT_PUBLIC_); they stay on the server.
criticalstaticfe-security
Why
Build tools copy every variable with these prefixes into the JavaScript sent to the browser, where anyone can read it in DevTools. A payment secret, database password or private API key with such a prefix is public the moment the site is deployed, and stays in old bundles and caches after you rotate it.
Fix
Rename the variable without the public prefix and use it only in server code (API routes, server actions, +server.js, server-only modules), then call that server code from the browser. Rotate any secret that was ever shipped. Keep only keys meant to be public (a publishable payment key, an analytics id) under the public prefix.
Examples
// bad: shipped to every visitor
fetch(url, { headers: { Authorization: `Bearer ${process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY}` } })
// good: server route reads STRIPE_SECRET_KEY; the browser calls /api/charges
fetch('/api/charges', { method: 'POST', body })Sources
Facts
- Id
security/no-secrets-in-client-env- Severity
- critical
- Check
- static checked in the source by
audit - Applies to
htmljsxvuesvelteastro- Taught by the skill
fe-securityFront-end security- Since version
- 0.1.0
Read it in the terminal
npx github:dawidolko/frontend-skills explain security/no-secrets-in-client-env