What does 'client-exposed secret' mean?
Your framework compiles anything under its public prefix straight into the browser bundle, so a real credential sitting there is readable by anyone who loads the page. Gitignoring the file does nothing about that, which is why this warning is separate from the exposed-secret one and why it fires on a correctly ignored .env.local.
Dotvault raises it when the value can only be a secret: a Stripe or Anthropic secret key, a GitHub or Slack token, an AWS access key id, a webhook signing secret, or a key named SECRET, PASSWORD or PRIVATE_KEY. The fix is either a credential that is meant to be public, or moving the call that needs the secret onto your server.
It is deliberately quiet about everything else. A pk_live_ publishable key, a browser map token and a public DSN are all correct usage under a public prefix, so none of them are flagged. A warning you can only clear by deleting working code is a warning people learn to scroll past.
You only see it in a project where Dotvault has detected the framework that owns the prefix, because a prefix means nothing on its own. PUBLIC_ is significant in SvelteKit and Astro and meaningless in a plain Node project, and nothing gets bundled there at all. The prefixes covered are NEXT_PUBLIC_, REACT_APP_, VITE_ (in both Vite and Laravel projects), NUXT_PUBLIC_, GATSBY_, EXPO_PUBLIC_, PUBLIC_ for SvelteKit and Astro, and NEXT_PUBLIC_FIREBASE_.
Where a row is both client-exposed and sitting in a file git can see, you get this badge rather than two, because a bundle cannot be unpublished and a repo is yours. The tooltip names both facts.