Outrings
Web observability and evidence

How do I prove my website is secure?

What you can honestly demonstrate about your site's security, what nobody can prove, and how to make the claim checkable.

4 min read
Short answer

You cannot prove a site is secure — that is an unfalsifiable claim about every possible attack. What you can do is demonstrate specific, verifiable controls: which headers you send, what transport you negotiate, what you do not disclose. Make each one checkable and let the reader draw the conclusion.

Why "secure" is not a provable property

"Secure" is a claim about the absence of every vulnerability, including ones nobody has discovered. Nothing can establish that. Anyone asserting it plainly is either being loose with language or selling something.

What is provable is the presence of specific controls, each individually observable. That is a weaker claim and a far more useful one, because it can be checked rather than believed.

What you can demonstrate

ControlHow anyone verifies it
HTTPS enforced everywhereRequest http:// and observe the redirect
HSTS with a long max-agecurl -sI and read Strict-Transport-Security
A Content Security PolicyRead the Content-Security-Policy header
Clickjacking protectionX-Frame-Options, or frame-ancestors in CSP
MIME sniffing disabledX-Content-Type-Options: nosniff
Referrer restraintReferrer-Policy
A modern TLS configurationInspect the handshake: protocol and cipher
No version disclosureAbsence of Server and X-Powered-By details
A vulnerability reporting route/.well-known/security.txt

Every row is a fact about your responses that any visitor can confirm without your cooperation. That is what makes it a proof rather than an assurance.

What no external check can establish

Being explicit about this is part of the credibility, not a caveat that weakens it.

  • Application logic. Injection flaws, broken access control, insecure direct object references. These need code review and testing, not header inspection.
  • Dependency vulnerabilities. Requires knowing your dependency versions, which are not published — and version matching against CVE databases is explicitly out of scope here.
  • Internal posture. Patch cadence, access controls, secrets handling, backups. Invisible from outside by design.
  • Whether you have already been compromised. A well-run intrusion changes nothing observable from the outside.
A site with perfect headers can be trivially exploitable through its application code, and a site with mediocre headers can be run by a careful team. External measurement demonstrates hygiene. Hygiene correlates with competence and does not establish it.

Making the claim checkable

If you want to state a security posture publicly, the pattern that holds up is: state something specific, and link to where it can be verified.

  • Publish security.txt. A machine-readable contact route for vulnerability reports at /.well-known/security.txt. Cheap, and it signals that reports are welcome rather than treated as attacks.
  • Use a badge that links to a live audit, not a static graphic. A seal that is an image proves nothing; one that links to a re-runnable measurement can be checked by anyone.
  • Say what you do not do. "We do not store card details; payment is handled by X" is specific and verifiable. "Bank-grade security" is not a claim about anything.
  • Date it. A security statement with no date describes an unknown moment in the past.

A sensible order of work

  1. Enforce HTTPS everywhere and add HSTS with a long max-age.
  2. Add X-Content-Type-Options, X-Frame-Options and Referrer-Policy — minutes of work, no functional risk.
  3. Introduce a CSP in report-only mode, watch what it would have blocked, then enforce it.
  4. Remove version disclosure from server and runtime configuration.
  5. Publish security.txt with a real contact route.
  6. Re-measure and confirm each header is actually present in the served response, not merely in your configuration.

Step six matters more than it sounds. Headers set at the origin and stripped at the edge are common, and only measurement of the public response reveals it.

What our audit reports about this

Every item below is measured directly, not inferred. Run it against your own site and the result names the exact rule or header responsible.

  • Every security header present or absent, with the exact value, so a claim can be verified rather than asserted.
  • Negotiated TLS protocol and cipher, certificate validity and chain completeness.
  • Whether server or runtime version information is disclosed.
  • Whether security.txt exists and is well formed, alongside an explicit statement that CVE matching and application-logic testing are not covered.

For agents and scripts, the same measurement is at /api/v1/security?url=yoursite.com — see the API documentation.

Related questions

Is a security seal from a scanner worth anything?

Only if it links to a verifiable, re-runnable result. A static image proves nothing — anyone can add one, including sites that have never been scanned. The link is the entire value.

Should I publish which security tools I use?

Naming specific products and versions gives away more than it gains. Describing controls — "all traffic is HTTPS with HSTS, and payments are handled by a PCI-compliant processor" — is specific without being a target map.

Does a good header score mean I am not vulnerable?

No. Headers are the outermost layer. Application logic flaws are invisible to any external check and are where most real breaches originate. Header hygiene is necessary and nowhere near sufficient.

What is security.txt?

A short text file at /.well-known/security.txt giving researchers a contact route for reporting vulnerabilities. It is cheap to publish and materially increases the chance that someone who finds a problem tells you rather than someone else.

Read next

All 100 guides · How every check works · API for agents