By the SurfaceCheckr team. Every finding maps to a check we run in production - see our methodology.

The website security checklist: what to lock down, in order of what gets hit first

Most security checklists read like a wall of 60 items with no sense of which ones matter. This one is ordered by reality: what an outsider actually checks first, fastest, and most often. Work down it top to bottom and you close the highest-blast-radius holes before you spend time on the marginal ones.

Everything here is checkable from outside your site, with no login and no code access, because that is exactly the vantage point an attacker starts from.

The checklist, worst first

$ scan yoursite.com
critical/.env reachableDB URL and API keys readable by anyone
highDEBUG=True in prodstack traces leak code paths and config
highsk_live_ in JS bundlelive payment key served to the browser
mediumNo HSTS headerfirst request can be downgraded to HTTP
mediump=none DMARCanyone can spoof email from your domain
5 findings from outside, no login, no agent installed.
A single external pass. Each item is something a stranger can confirm from the public internet, in the order they tend to look.
  1. No exposed files. No /.env, /.git/config, /backup.sql, /wp-config.php.bak, or database dump answering a plain GET. This is the first thing bots probe and the highest-impact thing to get wrong: a readable .env is your database password and API keys in one download, no exploit required.
  2. No secret keys in your frontend. A sk_live_, an AKIA..., a ghp_, or a Supabase service_role key inlined into your JavaScript bundle is a live credential handed to every visitor. Publishable keys are fine; secret keys never are.
  3. HTTPS everywhere, with a redirect and HSTS. Plain http:// should redirect to https://, and an HSTS header should tell browsers to never try plaintext again. Without it, the very first request to your site can be downgraded and rewritten on a shared network.
  4. A valid, current TLS certificate. Not expired, not self-signed, hostname matches. An expired cert turns your site into a full-screen browser warning overnight.
  5. The core security headers. A Content-Security-Policy that actually restricts scripts, X-Frame-Options or frame-ancestors against clickjacking, X-Content-Type-Options: nosniff, and a sane Referrer-Policy. These are one-line headers that most sites skip.
  6. Session cookies flagged. HttpOnly, Secure, and SameSite on the cookie that says "this is a logged-in user." Without HttpOnly, a single cross-site scripting bug becomes a full account takeover.
  7. No open admin panels. No phpMyAdmin, Adminer, Grafana, or CMS admin reachable on the public internet with default or no credentials. These get found by scanning common paths in seconds.
  8. Email that can't be spoofed. An SPF record, and a DMARC policy stronger than p=none. Without them, anyone can send "reset your password" mail as your domain, into the inbox.
  9. No known-vulnerable libraries. No jQuery, Bootstrap, or CMS version on the page with a public exploit against it. Your version number is in the source, and bots match it to a CVE before they send a second request.
  10. A security.txt file. So when a researcher finds something, they have a way to tell you instead of telling the internet.

That order is deliberate. Items 1 and 2 are catastrophic and common, so they come first. By item 10 you are into good-hygiene territory that matters but rarely decides an incident.

What "website security best practices" actually means beyond the list

A checklist tells you what to close. The practices that keep it closed are a smaller, duller set, and they are what separate a site that passes once from a site that stays passed.

  • Keep secrets out of anything the browser receives. The single rule that prevents items 1 and 2: server-only values live in server-only places, never in a bundle, a comment, a build manifest, or an API response. If a value is a secret, assume anything the browser can fetch is public.
  • Default to closed, then open what you need. A database table, a storage bucket, an admin route, an API endpoint: start each one denying access, then grant exactly the access the feature requires. The opposite order, open then remember to lock, is how the open ones get shipped.
  • Patch on a schedule, not on an incident. Outdated libraries and CMS versions are the slowest-moving, most-exploited class there is. A monthly update pass beats an emergency one.
  • Re-check after every deploy. Security is not a one-time pass. A deploy can reopen a file, drop a header, or ship a new key. The surface changes every time you push, so the check has to repeat.

How to secure a website, step by step

If you are starting from "I have no idea what my site exposes," this is the shortest path from that to a clean checklist.

  1. Look at your site the way a stranger does. Open it in an incognito window with no login, open the browser's network tab, and watch every request the page makes. Each one is a call a stranger can make too. This alone surfaces most of items 1 through 6.
  2. Try the files bots try. Type yoursite.com/.env, /.git/config, /backup.sql into the address bar. A 404 is what you want. A 200 is an emergency.
  3. Read your response headers. curl -sI https://yoursite.com shows your headers, your redirect behaviour, and your cookie flags in one shot. Compare them against items 3 through 6.
  4. Check your DNS and email records. Look up your SPF and DMARC records. A missing SPF record or p=none DMARC is item 8, unclosed.
  5. Fix worst-first, then re-check. Close item 1, redeploy, confirm the GET now 404s. Work up the list. Do not move to headers while a .env is still readable.

If most of your app was written by an AI assistant, run this pass twice, because the model wrote a working feature and did not check what it exposed. That gap has its own guide in vibe coding security, and the founder-speed version is the MVP security checklist.

Check the whole list from outside in a couple of minutes

Every item on this checklist sits on the outside of your perimeter, which means a passive external scan can confirm all of them in one pass. SurfaceCheckr requests the files a bot would request, reads the JavaScript you actually shipped, probes common admin paths, and inspects your headers, cookies, TLS, DNS, and email records, all from the public internet with no login and nothing installed. You point it at your URL and read back exactly which checklist items are green and which are open.

Be clear on the edge of that: an external scan sees the surface a stranger sees. It catches the readable .env, the leaked key, the missing header, the spoofable domain. It does not log in to test whether one user can read another's data, and it will not find a logic bug in your checkout. That deeper work is a pentest, and we say so out loud. The reassuring part is that the items that get hit first are almost all out front, which is exactly where this checklist, and this scan, look.

Frequently asked questions

What is website security? Website security is the practice of protecting a site and its data from being read, changed, or abused by people who should not have access. In practice it splits into two halves: what an outsider can reach without logging in (exposed files, leaked keys, weak headers, spoofable email, known-vulnerable libraries), and what a logged-in user can do beyond their own permissions (access-control bugs, logic flaws). This checklist covers the first half, the part a passive external scan can confirm, because it is where most real incidents begin and it is the cheapest to check.

What is the most important item on a website security checklist? No readable secret. An exposed .env file or a secret key in your frontend bundle hands over your credentials in a single request, no exploit required, and it is one of the most common holes on freshly shipped sites. Everything else on the list reduces risk; a leaked secret realises it. Close that first.

How often should I run a website security check? After every deploy, because a single push can reopen a file, drop a header, or ship a new key, and at minimum on a monthly cadence to catch newly disclosed library vulnerabilities. Security is not a one-time pass: your surface changes every time you change your site, so the check has to repeat. A monthly monitoring service exists precisely so you are told the moment something new gets exposed rather than finding out from an attacker.

Can I check my website's security for free? Yes. You can walk this entire checklist yourself with a browser and curl, and several free tools each check one band of it well. A free grade from a passive scanner will tell you, for any domain, the severity of what is reachable from outside in a couple of minutes. Seeing the exact findings and fixes is where the paid tiers come in, but the grade that tells you whether you have a serious problem is free.

Find it before someone else does.

Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.

External, read-only scan. We only request public URLs - never log in, never send attack traffic.