Which Vercel env vars should be Secret? How to check yours
Any private Vercel credential, such as a secret API key, access token, database password, or signing key, should be a Secret; Config is for values that are not secret, including a publishable key you ship to the browser on purpose, and neither type keeps a NEXT_PUBLIC_ value out of the browser.
By ShipSecurely Editorial · Updated · How we make these guides
Shows up in: Vercel, Next.js
What it is
Make every private Vercel credential a Secret: secret API keys, access tokens, database URLs with a password, signing keys, and webhook secrets. Config is for values that are not secret, such as a publishable key you ship to the browser on purpose. Whichever type you pick, a NEXT_PUBLIC_ value ships to the browser at build time.
Which Vercel environment variables should be Secret?
Vercel's docs split the two types by whether anyone can read the value back after saving. A Config value remains readable after saving for members with access, and the docs suggest Config for non-sensitive configuration such as public prefixes and values you may need to review later. A Secret value is write-only after saving. The August 24, 2026 changelog says the value remains available to your deployments and can be replaced, but members cannot view or retrieve it. The docs say to use Secret for passwords, API keys, and tokens. Vercel encrypts every value at rest either way. The type decides who can read it back.
In a typical vibe-coded app, that puts these in Secret: a Stripe secret key, a Supabase secret or service_role key, a model provider API key, a DATABASE_URL that contains a password, a session or JWT signing secret, an OAuth client secret, and a webhook signing secret. Config is for a site URL, a feature flag, an analytics ID, or the Supabase publishable key you already ship to the browser on purpose.
The type does not change what your code sends to the browser. Next.js inlines a NEXT_PUBLIC_ variable at build time into the JavaScript delivered to the client, replacing each process.env.NEXT_PUBLIC_... reference with a hard-coded value. Vercel's CLI docs say a variable with a public framework prefix, such as NEXT_PUBLIC_, is stored as Config. A credential under a public name is public no matter what label the dashboard shows. Rename it, read it only on the server, and rotate it. Secret keys shipped in the frontend and Public env vars, the Supabase anon key, and row level security cover that case.
What changed on Vercel in 2026?
On July 9, 2026, Vercel's changelog said build logs now replace a Sensitive variable's value with [REDACTED] when the value is 32 characters or longer. The section on build logs below has the current rule.
On August 24, 2026, Vercel replaced the Sensitive toggle with two types. When you add or edit a variable, you choose Config or Secret. The changelog says variables already marked Sensitive are treated as Secrets and keep working without migration, and that the environment variable list in the dashboard shows each variable's type and where it applies.
Secrets are allowed in Development now. The docs say this reverses the earlier rule that limited Sensitive variables to Production and Preview. In the CLI docs, a new variable defaults to Secret in Production, Preview, and custom environments, and to Config in Development. Because a Secret cannot be read back, vercel env pull keeps the real value already in your local file for that key. If the file has no real value, the CLI writes a placeholder for you to replace.
Two limits come with the write-only design. You cannot edit the key of a Secret after it is saved, and you cannot convert a saved Secret to Config in place. To store the same key as Config, delete the Secret and create a new Config variable.
The team policy changed too. The Enforce Sensitive Environment Variables policy is deprecated. It required every variable a team member created in Production and Preview to be Sensitive. The CLI docs say the CLI no longer enforces it. Its replacement is Separate Production Secret Values, an optional policy in the team's Security settings. A user with the Owner role can enable Require Separate Values. When it is on, each Secret must use a different value in Production than in Preview, Development, and custom environments, and the dashboard shows "Production must use a separate value." if you try to group Production with another target. The docs say teams that had the legacy policy enabled should review the new setting.
What happened in Vercel's April 2026 incident?
Vercel's security bulletin says: "As of October 16, 2026 at 10:19 AM PST, all remediation actions related to the security incident are complete, and the incident is closed."
The bulletin says the incident originated with a compromise of Context.ai, a third-party AI tool used by a Vercel employee. The attacker used that access to take over the employee's individual Vercel Google Workspace account, which gave them access to that employee's Vercel account. From there they pivoted into a Vercel environment and maneuvered through systems to enumerate and decrypt non-sensitive environment variables. The bulletin describes non-sensitive variables as those that decrypt to plaintext.
Vercel says it first identified a limited subset of customers whose non-sensitive variables were compromised, reached out to them, and recommended an immediate rotation of credentials. A broader review then found a small number of additional accounts compromised as part of the incident, and Vercel says it notified those customers. The same review found a small number of accounts with signs of compromise that appear to be separate from the April incident and do not appear to have originated on Vercel systems.
The bulletin's recommendations:
- Enable multi-factor authentication, with an authenticator app or a passkey.
- Review and rotate environment variables that were not marked sensitive. The bulletin says those values (API keys, tokens, database credentials, signing keys) should be treated as potentially exposed and rotated as a priority.
- Use the sensitive environment variables feature so secret values are protected from being read in the future.
- Rotate before you delete. The bulletin says deleting your Vercel projects or account is not sufficient, because compromised secrets may still provide access to production systems.
- Review the activity log for your account and environments.
- Investigate recent deployments for unexpected or suspicious ones, and delete any in question if in doubt.
- Set Deployment Protection to Standard at a minimum.
- Rotate your Deployment Protection tokens, if set.
The bulletin says "sensitive." Since August 24, 2026 that is the Secret type. Vercel's Deployment Protection docs say Standard Protection protects all deployments except production domains and is available on all plans.
How to check in 5 minutes
Open the Vercel dashboard, select the project, and open Environment Variables from the sidebar. Each variable in the table shows a Config or Secret label. Team-level variables are under Environment Variables in the team sidebar and carry the same labels.
Read every key labeled Config. A name with
KEY,SECRET,TOKEN,PASSWORD, orPRIVATEin it, or aDATABASE_URL, is a reason to inspect the value, not to rotate it automatically. If the value is a private credential, such as a secret API key or a database password, it goes on your rotate list. A key that is public on purpose, such as a publishable key you ship to the browser, can stay Config. Any private credential under aNEXT_PUBLIC_name goes on the rotate list too, whatever its label.Check where each credential applies. The list shows the environments for every variable. A Secret whose one value covers Production and Preview means your preview builds run with your production key. From a terminal,
vercel env ls productionandvercel env ls previewlist the variables for each environment.Open the team's Settings, then Security, and look at Separate Production Secret Values. If you are an Owner and Require Separate Values is off, decide whether to turn it on.
Open the build logs of your latest deployment and search for any credential printed in full. Then open the project's Settings, then Deployment Protection, and confirm it is at least Standard.
How to fix
Vercel
Work one credential at a time, in this order.
- Rotate at the provider first. Create a new key in Stripe, Supabase, your model provider, or your database. Keep the old one working for now.
- Save the new value as a Secret. In the dashboard, set Type to Secret and provide the new value. The docs say you choose Config or Secret when you add or edit a variable, and the conversion they rule out is a saved Secret back to Config. Give Preview and Development their own values. The docs say a Secret can have a different value per environment or Preview branch.
- Redeploy. Vercel's docs say changes to environment variables apply only to new deployments, so the running deployment keeps the old value until you redeploy.
- Revoke the old key at the provider once the new deployment works. Vercel's guide says a rollback points traffic at an older deployment whose values are exactly what they were when it shipped. After you revoke the old key, a rollback to a deployment from before the rotation runs with a dead key.
From the CLI, the documented flag is --type secret. Pass the value from a file rather than echo. The CLI docs warn that echo saves the value in your shell history.
vercel env rm STRIPE_SECRET_KEY production --yes
vercel env add STRIPE_SECRET_KEY production --type secret < new-stripe-key.txt
The CLI docs say success output includes a Type line, which should read Secret. --sensitive and --no-sensitive still work and map to Secret and Config. The August 24 changelog shows --visibility secret. The current CLI docs list --visibility as a deprecated alias for --type. Delete the key file when you are done.
Variables an integration created cannot be changed to Secret from the environment variable list. The docs give four steps:
- Disconnect the integration resource from all of its projects.
- Rotate the resource's secrets so the previous values are no longer valid.
- Reconnect the resource to each project. Deselect Development in the connection environments, then enable Sensitive in the advanced options. The docs say integration connections that include Development cannot enable Sensitive.
- Redeploy your projects to use the new values.
If you are a team Owner, turn on Separate Production Secret Values so a Production Secret cannot share a value with Preview or Development.
Next.js
Move any private credential out of a NEXT_PUBLIC_ name. The Next.js docs say a variable without that prefix is only available in the Node.js environment, so read it in a Route Handler, a Server Component, or a Server Action, and send the browser only the result. Rotate the old value at the provider. Next.js inlined it into the client JavaScript at build time, and the docs say a built app no longer responds to changes in those variables, so renaming it in the dashboard does nothing for the bundles already built.
Build logs only redact long Secrets
The current docs say that during builds, if a Secret value is 32 characters or longer and appears in the build logs, Vercel replaces it with [REDACTED]. A shorter Secret is not replaced. Vercel's environment variables guide says shorter API keys need manual care to keep them out of logs. The docs describe this redaction for Secret values. A Config value printed in a build log stays readable there.
Vercel always redacts the VERCEL_AUTOMATION_BYPASS_SECRET and VERCEL_OIDC_TOKEN system variables from build logs, whatever their length. Each time it redacts a Secret, Vercel records an Activity Log event for the masked key with the key name, project, and deployment, but not the value. The July 9 changelog says the Build Logs view also indicates when redaction happened.
Do not print environment values in build scripts. Remove env, printenv, and any console.log(process.env) from package.json scripts and build config. If an old build log shows a credential in full, rotate that credential.
Copy the fix prompt
Paste this into Cursor, Lovable, Bolt, or Claude Code. Read the diff before you merge it.
You are auditing environment variables in a Next.js app deployed on Vercel. Do not add features. 1. List every environment variable my code reads: process.env.*, import.meta.env.*, and any config file that loads env. 2. Classify each one as public (its name starts with NEXT_PUBLIC_ or VITE_, so it ships to the browser), Config (not secret, fine to read back), or Secret (a private API key, access token, password, database URL with a password, signing key, or webhook secret). A name containing KEY, TOKEN, SECRET, or PASSWORD means inspect the value, not that it is private. A publishable key meant for the browser is public, not Secret. 3. Never put a private credential in a NEXT_PUBLIC_ or VITE_ name. If one is there now, move the read to server code and give it a server-only name. 4. Never print env values in build scripts, logs, or error messages. Remove env, printenv, and console.log(process.env). 5. Output a table: key, where it is read, classification, and, for private credentials only, whether it must be rotated and re-saved as a Secret. Do not call the Vercel API or the Vercel CLI, and do not add, change, or delete environment variables without asking me first.
Questions
Is a Secret env var hidden from the browser?
Not by itself. Secret controls who can read the value back in Vercel: members cannot view or retrieve it after saving. It does not control what your code sends to the client. Next.js inlines a NEXT_PUBLIC_ variable into the browser JavaScript at build time, and Vercel's CLI docs say a public-prefixed variable is stored as Config. A server-only Secret also reaches the browser if your code returns it in a response.
Do I need to redeploy after changing a variable?
Yes. Vercel's docs say changes to environment variables are not applied to previous deployments and you must redeploy to update the value. Vercel's guide says to use the Redeploy button or push a new commit. A NEXT_PUBLIC_ value is fixed into the bundle when the app builds, so it needs a new build too.
Was my project affected by the April 2026 incident?
Vercel's bulletin says it contacted the subset of customers whose non-sensitive variables were compromised, and later notified a small number of additional affected accounts. The bulletin's recommendations still say to rotate variables that were not marked sensitive and to treat those values as potentially exposed. If a private credential was stored as Config, or was non-sensitive before August 24, 2026, rotate it and save the new value as a Secret. A publishable key you ship to the browser on purpose was already public.
Sources
- Vercel docs: Config and Secret environment variables
- Vercel changelog, August 24, 2026: Environment variables now use Config and Secret types
- Vercel changelog, July 9, 2026: Build logs now redact Sensitive Environment Variable values
- Vercel: How to add and manage environment variables on Vercel
- Vercel April 2026 security incident bulletin
- Vercel CLI: vercel env
- Vercel docs: Environment variables
- Vercel docs: Managing environment variables
- Vercel docs: Deployment Protection
- Next.js: How to use environment variables
Related
Guides
Incidents
- Node.js fixed a Brotli decoder bug that can run code, and Vercel says Node 20 projects must move to 22 or 24
- Vercel closed its April 2026 incident that exposed non-sensitive environment variables
- Vercel patched Linux kernel flaw CVE-2026-98432 on its hosts, and Linux servers you run yourself need a kernel update and reboot
Need someone to fix it for you? See /help.
The weekly fix
The weekly fix: 3 real security mistakes in vibe-coded apps and how to fix them, every Tuesday.