The Website Security Checklist for 2026 — Sorted by How You Actually Verify Each Item
Most checklists tell you what to do and leave you no way to know whether it is already done. This one is sorted by how each item is verified: what a scanner confirms in seconds, what needs a person, and what no tool can answer for you.
Webcuris Research
·8 min read

Search for a website security checklist and you will find the same thirty imperatives, phrased slightly differently, on every result. Enable HTTPS. Set your headers. Keep your dependencies updated. All true, all useless in the same specific way: you finish reading knowing what you should have done, and no more certain about what you have done than when you started.
The missing column is verification. "Set a Content-Security-Policy" is advice; "your CSP contains 'unsafe-inline', which means it passes every presence check and blocks no injection" is a finding. The distance between those two sentences is the entire difficulty of security work, and almost every checklist stops on the wrong side of it.
So this one is sorted by how you find out. Three groups: items a scan confirms in seconds, items that need a person to look at something, and items that are policy decisions no tool can make on your behalf. Each automated item names the check that performs it.
Group one: a scan answers these in seconds
Every item here is a machine-checkable fact about what your server already sends. There is no judgement involved, which is exactly why leaving them to human attention is a mistake — they are the items most likely to be quietly true today and quietly false after next Thursday's deploy.
The response headers
| Item | What actually goes wrong without it | Check |
|---|---|---|
| Strict-Transport-Security is set, with a max-age of at least a year | A visitor who types the bare domain, or follows an old http:// link, can be downgraded to plaintext before the redirect ever runs. HSTS is the instruction that stops the first request being interceptable. | Page fetch |
| Content-Security-Policy exists and does not contain 'unsafe-inline' | A policy with 'unsafe-inline' passes every presence check and stops no injection, because inline script is precisely what an injection is. This is the single most common way a header audit reports green on a site with no protection at all. | Content-Security-Policy |
| X-Frame-Options or frame-ancestors is set | Without it your page can be framed invisibly over an attacker's, and a click your user believes is on their page lands on yours. frame-ancestors in CSP supersedes the older header; either satisfies this. | Page fetch |
| X-Content-Type-Options: nosniff | A browser that sniffs content type can be persuaded to execute an uploaded file as script. One header, no downside, and it is missing more often than not. | Page fetch |
| Referrer-Policy does not leak full URLs cross-origin | The default on many stacks sends the full path off-site. If any of your URLs contain a token, an account id, or a password-reset link, that is where it goes. | Page fetch |
| Cache-Control on authenticated responses forbids shared caching | A page that sets a session cookie and is cacheable by a shared cache is one CDN misconfiguration away from serving one user's session to another. | Caching headers |
The cookies
| Item | What actually goes wrong without it | Check |
|---|---|---|
| Session cookies carry Secure | Without it the cookie is sent over plaintext HTTP, which means it is sent to anyone on the network path the first time a link resolves to http://. | Cookie attributes |
| Session cookies carry HttpOnly | Without it, any successful XSS reads the session directly. HttpOnly does not prevent XSS; it decides whether XSS costs you a defaced page or every logged-in account. | Cookie attributes |
| Session cookies carry SameSite=Lax or Strict | Without it the browser attaches the cookie to cross-site requests, which is the mechanism CSRF depends on. | Cookie attributes |
The transport and the names
| Item | What actually goes wrong without it | Check |
|---|---|---|
| TLS 1.2 or better, with no known-weak cipher suites | Older protocol versions are not merely dated; several have practical downgrade and padding attacks with public tooling. | TLS configuration |
| The certificate is valid, matches the hostname, and is not near expiry | Expiry is the outage that arrives on a Sunday. It is also the most predictable event in your entire infrastructure, which makes being surprised by it a monitoring failure rather than a certificate one. | TLS configuration |
| http:// redirects to https://, on every hostname you answer on | A site that serves HTTPS correctly on www and plaintext on the apex has not migrated; it has half-migrated, and the half that is wrong is the one people type. | Plain-HTTP upgrade behaviour |
| An SPF record exists and is not permissive | Without SPF, anyone can send mail as your domain. With a permissive one that ends in +all, you have published a record that says they may. | DNS records |
| A DMARC record exists, and eventually enforces | p=none is a monitoring policy, not a defence: it collects reports while spoofed mail continues to be delivered. It is the correct first step and the wrong resting place. | DNS records |
| A CAA record restricts who may issue certificates for you | Without one, any publicly trusted CA can issue for your domain, so the pool that would have to be compromised or tricked is every CA rather than yours. | DNS records |
| CORS does not reflect arbitrary origins with credentials | Reflecting the request's Origin while allowing credentials is functionally 'any website may make authenticated requests as your users'. It is usually introduced to fix a local development problem. | CORS policy |
Group two: automated, but only on a domain you have proven
These are equally machine-checkable and deliberately not available to an anonymous caller, because each one involves asking your server for things a visitor would not ask for. Enumerating subdomains, requesting paths to see which exist, or reading a JavaScript bundle to find the endpoints it calls are all reasonable on your own estate and reconnaissance on somebody else's. The distinction is authorisation, not packet volume.
- No secrets in your client bundle. API keys, tokens and internal URLs compiled into JavaScript are published, not hidden — minification is not encryption. Client bundle analysis.
- No exposed paths.
.git,.env,.DS_Store, backup files and directory listings, checked by request rather than assumed absent. Exposed-path probing. - Your subdomains are known to you. Certificate transparency logs make every certificate you have ever issued public, which means your subdomain list is already published whether or not you maintain one. Certificate-transparency subdomain discovery.
- No subdomain points at a service you no longer own. A CNAME to a deleted bucket or a cancelled SaaS account is a hostname somebody else can claim and serve content from, under your name and your cookies. Subdomain takeover candidates.
- Your API surface matches what you documented. Endpoints called by the client but absent from the specification sit outside every process that used the specification — the review, the gateway rules, the contract tests. API surface discovery.
- No introspection open on production GraphQL. Introspection hands an attacker the complete schema, which turns exploration into enumeration. API surface discovery.
- Your CMS plugins are current and unabandoned. Public plugin directories publish last-updated dates and version numbers; matching them against what you run is arithmetic, not judgement. WordPress plugin directory check and WordPress plugin CVE matching.
- Your dependencies have no known-exploited vulnerabilities. Not the same as 'no vulnerabilities' — the useful question is which of them are actually being exploited, which EPSS answers and CVSS does not.
Group three: no scanner can answer these for you
The last group is the one every automated checklist quietly drops, because it cannot be scored. These items are not harder to fix than the ones above. They are harder to notice, which is worse.
- Every admin account has multi-factor authentication. A tool can see that your login page exists. Whether the four people who can delete your production database have MFA is a question only your identity provider can answer, and only if somebody asks it.
- Someone who left last quarter cannot still log in. Offboarding is a process failure, not a configuration one, and it is invisible from outside.
- You have a restore, not just a backup. An untested backup is a belief. The item is 'restored one, recently, and timed it'.
- Somebody is named for the security inbox. Findings arrive from strangers — researchers, customers, an automated report. A security.txt with an address nobody reads is worse than none, because it advertises a channel you are not on.
- You know what you would do in the first hour of a breach. Not a document. Who is called, who can revoke credentials at 3am, and where that is written down where they can reach it without the compromised system.
- Your third parties are on the list. Every script tag from another origin is code you execute and do not control. The checklist item is knowing how many there are.
The item that makes the list worth keeping
A checklist is a photograph. Everything in group one can be true today, verified this morning, and false by Friday — a header dropped when a proxy was reconfigured, a cookie flag lost in a framework upgrade, a certificate that renews automatically until the automation breaks. None of those announce themselves, and all of them are exactly as invisible as the day before you first fixed them.
So the last item is: something re-reads this list on a schedule and tells you when an answer changes. That is the difference between having done the work and knowing it is still done — and it is the reason a one-off scan, this article included, is a starting position rather than a result.
Keep reading

The CSP that killed our own form (a production-only Next.js bug)
The forgot-password form is not working at all. Not "it's slow." Not "I got an error." Not working at all. So we did what you do. Checked the error tracker: clean. Checked the…

Secure, HttpOnly, SameSite: Cookie Attributes Explained by What Goes Wrong Without Them
Three attributes, three specific attacks. What each one stops, what happens on the day it is missing, and the one line of Set-Cookie a session cookie should carry.

A Content-Security-Policy That Reports as Present and Defends Nothing
A script-src carrying 'unsafe-inline' passes every presence check and stops no injection. The theatre policy, the working one, and the war story of a strict CSP that broke sign-up with no error anywhere.
Everything this article describes is what Webcuris checks continuously — scan one page free, no signup.