Securealy
Check · Launch hygiene · medium · local

Hosting env values are clean and scoped

No value ends in a newline; production and preview values are scoped; no secret sits in a NEXT_PUBLIC_ or VITE_ name.

Severity
medium
Tier
Local: runs on your machine with your own keys
Category
Launch hygiene
Fix
Summary below; full runbook in the Fix Kit, Module 00: Foundations
Id
vercel-env-hygiene

What this means

Passing means three things hold in your hosting environment variables: no value ends in a newline, Production and Preview have their own values, and no secret lives under a NEXT_PUBLIC_ or VITE_ name. Failing means one of those is wrong. A trailing newline corrupts the secret, a shared value lets a preview touch production, and a public prefix ships the secret to the browser.

How we test it

This is a local check. You run npx securealy check-vercel-env on your own machine with your own Vercel credentials; it pulls the variables to a temporary ignored file, inspects them, and deletes the file. Nothing leaves the machine and no value is printed. A value ending in a newline or whitespace, or a secret-shaped value under a NEXT_PUBLIC_ or VITE_ name, is a fail. A variable set for Production with no Preview value is a warn.

Why it matters

A trailing newline in a Stripe key fails every charge with a misleading error. In Kenny Hyder's estate a sports data product set its payment keys with echo "value" | vercel env add; echo appended a newline, the SDK put it in the Authorization header, and the error read "connection error, retried 2 times". It looked like the network and was one extra byte, found only by pulling the env file and counting characters. A NEXT_PUBLIC_ service key is published to anyone who reads page source, and a preview that reads the production database is a staging environment that can corrupt production.

The fix

Delete and re-add every affected variable with printf %s "VALUE" | npx vercel env add NAME production (or paste it in the Vercel dashboard, which adds no newline), move any secret out of a NEXT_PUBLIC_ or VITE_ name into a plain server-side name, and give Preview its own values such as a test database and test payment keys. Then add .trim() to every server-side env read so the class cannot recur.

The full runbook is in the Fix Kit, Module 00.

Prompt for your AI

Paste this into the coding agent that built the app. It reproduces the finding and stops before changing anything; the fix steps are in the kit.

Do not change any Vercel setting or any file. Ask me before running vercel env pull, because it writes real values to disk.
With my yes, run: npx vercel env pull .env.check --environment=production --yes
Run: grep -nE '\\n"?$' .env.check; echo "newline-suffixed values: $?" and show me the output. Exit 1 means none.
Run: awk -F= '/^[A-Z]/{ v=$2; gsub(/^"|"$/,"",v); if (v ~ /[[:space:]]$/) print "TRAILING WHITESPACE:", $1 }' .env.check and show the output.
Print only the NAMES that start with NEXT_PUBLIC_ or VITE_ and tell me which look like server secrets by name (service, secret, key). Never print a value.
Run: npx vercel env ls and list the names that exist for Production but not Preview.
Tell me what it would take to fix each finding, and stop before changing anything.
Finally run: rm -f .env.check && git check-ignore .env.check; echo $? and show the result. Expected 0, meaning a leftover copy would be ignored.

Next

Grade your own URL

Every grade lists this check with its evidence for your site. Two free grades a day.