NETLIFY SECURITY CHECKLIST
Netlify pioneered the “git push deploys to a URL” model. Most Netlify security failures come from the same patterns: env vars scoped too broadly, deploy previews exposed publicly, Functions that skip auth checks, Forms whose submissions are readable from the admin without restriction, and _redirects rules that turn into open redirects. The checklist below is what we look for first when we audit a Netlify deployment.
Treat Critical as launch-blocking. High is week-one. Medium is the cleanup once you have users.
How to use this checklist
Walk it once in the Netlify dashboard for your production site, ticking items as you go. After each fix, deploy a preview and re-test against the preview URL. After the whole list passes, run a black-box scan against the production domain.
Critical (fix before launch)
1. Move secrets to Netlify env vars, scoped to functions only
Why it matters. Netlify env vars are accessible to the build process and to Functions by default. If a build step inlines them into the static output (e.g. VITE_* in a Vite build, GATSBY_* in Gatsby), the values ship in the bundle.
How to check. Site configuration → Environment variables. For each var, check the “Scopes” — confirm secrets are scoped to “Functions” only, not “Builds” or “All”.
How to fix. Re-scope. Move secret-bearing API calls to Functions. For static-site frameworks, never reference secrets via build-time inlining variables.
2. Configure deploy preview password protection on private projects
Why it matters. Netlify deploy previews are publicly reachable by default. Search engines crawl them; PR descriptions leak the URLs; attackers find unfinished work and pre-launch features.
How to check. Site configuration → Access control → Site protection. For private projects, confirm password protection or SSO (Pro/Enterprise) is enabled on previews.
How to fix. Enable site password or SSO for previews. For pre-launch sites, also gate production until launch day.
3. Audit Netlify Functions for missing auth checks
Why it matters. Netlify Functions get a request and return a response. Auth is up to you — and AI-generated function code routinely skips the auth check entirely, returning data based on a userId from the request body.
How to check. Open every file under netlify/functions/. For each, confirm the first lines verify the user’s identity (via cookie, JWT, Netlify Identity, or whatever auth provider) and reject unauthorized requests. Confirm any user ID used in queries comes from the verified identity, not from the body.
How to fix. Add an assertAuth helper at the top of every function. Reject unauthenticated requests with 401.
4. Verify Form submissions are not publicly readable in admin
Why it matters. Netlify Forms collects submissions and shows them in the dashboard. Submissions sometimes contain PII, password reset emails, or contact form contents that shouldn’t be readable by every team member.
How to check. Forms → [form name]. Audit who has dashboard access; review the data being collected.
How to fix. Restrict team access to forms with sensitive data. For sensitive forms, send via webhook to a database you control instead.
5. Restrict deploy hooks to authorized services
Why it matters. Deploy hooks are URLs that trigger redeployment. Anyone with the URL can deploy your site at will, which is both a DoS vector (forced builds eat your build minutes) and a stale-data vector (attacker triggers a rebuild after they’ve poisoned a CMS).
How to check. Site configuration → Build & deploy → Build hooks. List every hook; identify which service uses each one.
How to fix. Delete unused hooks. Rotate any hook that’s been shared in PR descriptions, Slack threads, or client emails.
6. Audit _redirects and netlify.toml for open-redirect patterns
Why it matters. _redirects rules with * source and a query-parameter destination can become open redirects. Open redirects are a common phishing vector — your trusted domain bouncing users to an attacker URL.
How to check. Read _redirects and netlify.toml redirects in full. Patterns like /go/* https://:splat or any rule that interpolates a query parameter into the destination is suspect.
How to fix. Replace dynamic destinations with explicit allowlists. If you need link-shortener behavior, store the mapping server-side.
High (fix in the first week)
7. Enable Netlify Identity rate limits and password rules
If you use Netlify Identity, configure password length (≥ 12), enable HaveIBeenPwned-equivalent breach-list checks, and set per-IP rate limits on signup, password reset, and login.
8. Configure CSP and security headers in netlify.toml
Netlify doesn’t add CSP, HSTS, or X-Frame-Options by default. Add via [[headers]] blocks in netlify.toml.
9. Pin Functions runtime version
In netlify.toml, pin [functions] node_bundler and runtime version. Auto-upgrades through major Node versions can change crypto and HTTP defaults.
10. Restrict team access by role
Team → Members. Audit who has Owner / Member / Reviewer. Owners can change every setting; Reviewers can deploy. Downgrade where you can.
11. Verify domain and DNS are locked
Netlify DNS or external DNS — either way, confirm the registrar has DNSSEC enabled if available, and audit who can change DNS records.
12. Set up build-time secret scanning
Add gitleaks or trufflehog to your build command. Fail the build if a secret is detected in committed code.
Medium (fix when you can)
13. Audit redirect rules for open-redirect patterns
Beyond item 6, periodically re-audit. Redirects accumulate; old marketing campaigns leave behind dynamic redirects nobody remembers.
14. Disable analytics PII collection
Netlify Analytics is server-side; confirm the URL paths it collects don’t contain user IDs, emails, or session identifiers.
15. Document deploy contexts
A short doc covering what each Netlify context (production, deploy-preview, branch-deploy) is for, and what env it should have.
16. Pin build image version
Netlify offers multiple build images. Pin the version in netlify.toml rather than latest.
17. Audit installed Netlify Add-ons
Each add-on is attack surface. Audit; remove unused.
18. Set up alerting on deploy frequency anomalies
A sudden spike in deploys signals a compromise of a deploy hook or a developer account.
After every config change
- Re-test a preview URL — confirm authentication and env scoping behave as expected.
- Re-verify Functions still require auth.
- Re-check
_redirectsfor any new dynamic destinations.
Common attack patterns we see in Netlify deployments
The Function with no auth. AI-generated netlify/functions/getUserData.js reads userId from the query string and queries the database. Anyone calling /api/getUserData?userId=42 gets user 42’s data.
The leaked deploy hook. Deploy hook URL pasted into a PR description on a public repo. Attacker uses it to force-deploy on every push, eating the team’s build quota.
The open redirect. /_redirects had /r/* https://:splat 302. Attacker emails phishing link https://yoursite.com/r/evil-domain.com/login — the trusted domain bounces users to attacker.
The leaked form data. Netlify Form for “report a bug” collects every submission including stack traces with internal URLs. Every team member can read them; an exiting employee exfiltrates the lot.
Related Resources
How to Secure Netlify
Step-by-step guide for hardening a Netlify deployment — env scoping, Functions auth, redirect hygiene, and the headers patterns above in long form.
Is Netlify Safe?
In-depth analysis of Netlify’s defaults — what’s locked down, what’s exposed, and what we find when we audit a typical Netlify-deployed app.
Automate Your Checklist
A checklist tells you what to look for. A scanner tells you what’s actually broken in the deployed app right now. VibeEval drives a real browser through your Netlify deployment, attempts the missing-auth and open-redirect attacks above, and reports what got through.
SCAN YOUR DEPLOYMENT
14-day trial. No card. Results in under 60 seconds.