DEPLOYMENT SECURITY
The platform you deploy to changes the security model more than people expect. Build-log scrubbing, env-var scoping, edge function isolation, redirect rules — each platform exposes different surfaces. This hub covers the deployment-time controls that catch problems before users do.
Why deployment security gets skipped
Deployment is the boundary where your code stops being your problem and starts being someone else’s infrastructure. AI coding tools optimise for “it works on my machine”; the moment the app moves to a hosted platform, a different set of controls take over. Most builders learn the deployment-side gaps the hard way:
- A Vercel preview URL accidentally indexed by Google because robots.txt wasn’t set
- A Railway env var leaked in build logs because a
console.log(process.env)survived a debugging session - A Netlify redirect rule that turned a path-traversal bug into a public S3 fetch
- A Docker image with the build-time
npm installcache containing every node_module’s original source — including comments with hardcoded test credentials
None of these are bugs in the app code. They’re side effects of the deployment configuration the AI tool didn’t write — and that nobody reviewed because it lives in a .toml, a YAML file, or a dashboard nobody opens after the first deploy.
Pick your platform
| Hosting on | Start here | Then add |
|---|---|---|
| Vercel | Vercel Security Guide | Environment variables, SSL/TLS setup |
| Netlify | Netlify Security Guide | Production checklist |
| Railway | Railway Security Guide | Environment variables, CI/CD security |
| Render | Render Security Guide | Production checklist, Docker security |
| Self-hosted / Docker | Docker Security Basics | SSL/TLS setup, CI/CD security |
Platform-specific guides
- Vercel Security Guide — preview URL exposure, edge function isolation, environment scoping (Production / Preview / Development), the
vercel.jsonheaders block, and the redirects/rewrites patterns that turn into accidental open proxies. - Netlify Security Guide —
_headersand_redirectssyntax, Functions auth, Forms abuse, build-log scrubbing, and the Netlify Edge / Background Functions security boundary. - Railway Security Guide — service-to-service networking, env var scoping per environment, build-time vs run-time secret exposure, public vs private domains.
- Render Security Guide — service types and their default exposure, health-check endpoints leaking version info, private services on the Render network, and disk-mounted secrets.
Cross-platform practices
- Production Security Checklist — the master pre-launch pass. Headers, secrets, rate limits, error handling, monitoring. Use as a gate before any “v1.0” deploy.
- Environment Variables Security — the realistic threat model for env vars: build-log leakage, prefixed-vs-unprefixed (NEXT_PUBLIC_, VITE_) accidentally shipping to the browser, secret rotation across platforms, and how to avoid the “10 vars, 4 stale” drift.
- CI/CD Security Guide — securing automated deployments: GitHub Actions secrets, OIDC instead of long-lived tokens, supply-chain attacks via untrusted Actions, branch protection that survives an agent attempting to bypass it, and the audit trail you’ll want when something breaks.
Configuration and infrastructure
- Docker Security Basics — base-image selection (distroless, alpine pitfalls), multi-stage builds that don’t leak the build-stage layer into runtime, non-root user, read-only filesystems, and the secret-handling patterns that don’t end up in
docker history. - SSL/TLS Setup Guide — modern TLS configuration, certificate automation (Let’s Encrypt, ACME), HSTS preload, OCSP stapling, the cipher suites worth disabling, and the testing tools (testssl.sh, SSL Labs) for verifying.
The 60-minute pre-launch deployment audit
Before any “we’re going live” moment, run through this in order:
- Confirm preview URLs are not indexed.
robots.txtdenying/, or auth gating, or platform-level password protection. Otherwise Google indexes your preview deploys and your secret features ship to search. - Audit environment variables. Every var, every environment. Anything ending in
_KEY,_SECRET,_TOKENshould not have aNEXT_PUBLIC_/VITE_/REACT_APP_prefix. Secret rotation date for each — anything older than the last team member departure needs rotation. - Check build logs for leaks. Look at the last successful build log. Search for any value that matches a secret pattern (
sk_,ghp_, base64-y JWT-shaped strings). If anything is there, the secret is in your CI history forever — rotate. - Verify headers are applied.
curl -I https://yourapp.com/and check for HSTS, CSP, X-Frame-Options, X-Content-Type-Options. Use the free headers checker for the full grade. - Test redirects and rewrites. Each rule in
vercel.json/_redirects/ etc. — does it accept user input that could redirect off-site, or rewrite to an internal endpoint that wasn’t supposed to be public? - Confirm Functions / Edge Functions enforce auth. List every function endpoint. For each, send an unauthenticated request. If it returns 200 with data, fix.
- Validate the deploy artifact contents. For Docker:
docker historythe final image, look for layers containing build-time secrets. For static sites: check the deployed bundle for any leaked keys (token leak checker). - Set up alerting. At minimum: 5xx error rate spike, sudden traffic anomaly, deploy-failed notification. Without this you discover problems via support tickets, hours after they started.
Common mistakes
- Leaving preview deploys public. Every preview is a complete copy of your app with the same backend access. If they’re public, every PR open is a soft launch.
- Treating
.envas the source of truth in production. A platform’s secret manager (Vercel env vars, Railway variables, Render secrets) is the source of truth..envfiles in repos drift and leak. - Putting build steps in the runtime image. A multi-stage Dockerfile that copies
.git,node_modules, or the build cache into the final image bakes secrets and source maps into every container that ships. - Trusting the platform’s defaults to be secure. They aren’t. Vercel doesn’t add CSP. Netlify doesn’t enforce auth on Functions. Railway doesn’t isolate services by default. The defaults are what gets you to “deployed”, not “safe”.
- Forgetting the CI auth keys. Long-lived deploy tokens in CI secrets are higher-value targets than user creds — they ship code straight to prod. Rotate, scope, prefer OIDC.
- Configuring
0.0.0.0instead of127.0.0.1on internal services. Means anything on the deploy network can reach your “internal” service. Real isolation requires platform-level network rules.
Related resources
- Free Security Headers Checker — grades your deployed headers, returns paste-ready fix configs for each platform above.
- Free Token Leak Checker — scans the deployed bundle for keys the build process accidentally shipped.
- Vibe Code Scanner — full runtime probe across the deployed app.
- Backend Security — pair with deployment security; the platform protects the perimeter, the backend protects the data.
- Free Security Self-Audit — 30-minute manual checklist that includes the deployment-side items above.
SCAN BEFORE PRODUCTION
Catch deployment-side gaps before the launch tweet. 14-day trial. No card.