How to Add security.txt to Your Site

You can do this

A plain text file telling researchers how to report a problem to you. On your own server it is a ten minute job. Getting it right, and keeping it right, takes slightly more thought than most guides admit.

You control the server, so nothing is in your way. The two things people get wrong are the content type and the Expires field.

What it is for

Someone finds a problem on your site. Maybe an exposed file, maybe a bug in a form. They want to tell you. They look at your contact page, find a sales enquiry form, and decide it is not worth their afternoon. So they do nothing, or they post about it.

security.txt is the fix. It is a plain text file at a known location that says who to contact and how. It is defined by RFC 9116, it costs nothing, and it is the cheapest security improvement on this entire site. Our security.txt glossary entry is the short version.

The rules that are actually MUSTs

RFC 9116 is short, and four of its requirements are not suggestions.

  • It MUST be at /.well-known/security.txt. Not at /security.txt. The RFC does sanction a redirect from the legacy top level /security.txt to the .well-known path, but only in that direction, never the reverse.
  • It MUST be served over https.
  • It MUST be served as Content-Type: text/plain; charset=utf-8. This is where most self-hosted attempts quietly fail. Serving it as text/html, which is what happens if you make it a CMS page, violates the spec.
  • Contact: is mandatory. The RFC's wording is that this field "MUST always be present". A file without it is not a valid security.txt.
  • Expires: is mandatory too. It "MUST always be present and MUST NOT appear more than once". This is the field everyone misses, because it was added in RFC 9116 and older examples predate it.

The minimal valid file

This is complete. Two fields, nothing else needed.

Contact: mailto:[email protected]
Expires: 2027-01-01T00:00:00.000Z

Save it as security.txt in a .well-known directory at your web root. That is all the file needs to be valid.

Expires is a commitment, not a formality

Worth being clear about this before you file it under done.

The RFC recommends Expires be less than a year in the future. That is deliberate. It forces the file to be maintained, so a researcher can trust that the address in it is still monitored rather than belonging to someone who left in 2023.

Which means security.txt needs recurring maintenance. Put a reminder in a calendar now. An expired security.txt is itself a finding, and arguably a worse look than not having one, because it says you did this once and stopped caring.

Some genuinely useful advice: point Contact at a role address like security@ that forwards to a team, never at a person. People leave. Roles do not.

Fixing the content type on Apache

If your server serves the file as something other than text/plain, this is the fix.

<Files "security.txt">
    ForceType text/plain
</Files>

Check the result with your browser dev tools or a HEAD request. Do not assume, because a wrong content type is invisible until someone checks.

The warning that matters most on this page

Never blanket-deny or blanket-redirect /.well-known/.

It looks like a tidy hardening move. It is a certificate outage with a delay on it. Let's Encrypt and cPanel AutoSSL validate your domain through /.well-known/acme-challenge/. Block that path, or redirect all of /.well-known/ somewhere, and certificate renewal fails. You will not notice, because your existing certificate keeps working. You notice ninety days later when it expires and your site starts throwing browser warnings.

If you have rules blocking dot-directories, which some hardened configurations do by default, make sure .well-known is explicitly excluded. Add the file, then confirm your next renewal succeeds. Our SSL guide covers the renewal side.

Optional fields worth adding

The two mandatory fields are enough. These are the ones that earn their place.

Canonical

The URL this file is meant to live at. It tells a reader they are looking at the real thing and not a copy served from somewhere unexpected.

Policy

A link to your vulnerability disclosure policy. If you have one, link it. It sets expectations about what you will and will not do with a report.

Encryption

A link to a public key, so a reporter can send you sensitive detail safely. Only add it if someone can actually decrypt what arrives.

Preferred-Languages

The languages your team reads. Cheap, and genuinely helpful to a researcher deciding whether to bother.

Acknowledgments

A page thanking people who have reported issues. It is a small thing that materially changes whether researchers come to you first.

Hiring and CSAF

Hiring links to security roles. CSAF points to machine readable advisories. Both are real fields in the spec, both are for larger operations.

A fuller example

What a well maintained file looks like in practice.

Contact: mailto:[email protected]
Contact: https://example.com/security-report
Expires: 2027-01-01T00:00:00.000Z
Canonical: https://example.com/.well-known/security.txt
Policy: https://example.com/security-policy
Preferred-Languages: en
Acknowledgments: https://example.com/security-thanks

Contact may appear more than once, in order of preference. Expires may not. Keep the Expires date under a year out and diarise the update.

Confirm it

Request https://yourdomain.com/.well-known/security.txt and check three things: it returns 200, the body is what you wrote, and the Content-Type header says text/plain. All three, not just the first.

Then run a free check to see it alongside everything else, or browse the rest of the fix-it guides.

Check your work in seconds

Run your site through our free safety check to confirm the fix is live, and see what else a shopper would notice.

Run a free check

Frequently asked questions

Can I put security.txt at the root of my site instead?

Not as the only copy. RFC 9116 requires /.well-known/security.txt. The RFC does sanction a redirect from the legacy top level /security.txt to the .well-known path, but only in that direction. A file at the root with nothing at .well-known does not satisfy the spec.

Why does my security.txt fail validation when the file is there?

Two usual suspects. Either the Content-Type is not text/plain, which happens when the file is served through a CMS or with the wrong mapping, or the Expires field is missing. Expires is mandatory under RFC 9116 and is very commonly absent because it was added in that revision and older examples predate it.

What should Expires be set to?

Less than a year in the future, which is what the RFC recommends. That is intentional: it forces you to keep the file current so a researcher can trust the contact address still works. It also means this is a recurring task. Set a calendar reminder, because an expired security.txt is itself a finding.

Is it safe to block /.well-known/ on my server?

No, and this is the most expensive mistake on this page. Let's Encrypt and cPanel AutoSSL validate your domain through /.well-known/acme-challenge/. Blocking or blanket-redirecting that path breaks certificate renewal, and you will not find out until your current certificate expires. If you deny dot-directories, exclude .well-known explicitly.

Do I need a PGP key for security.txt?

No. Contact and Expires are the only mandatory fields. The Encryption field is optional, and only worth adding if someone on your side can actually decrypt what arrives. A key nobody holds is worse than no key, because it invites reports you cannot read.

How do I fix the content type on Apache?

Wrap the file in a Files block and force it: ForceType text/plain . Then verify with dev tools or a HEAD request rather than assuming, because a wrong content type is invisible from the page itself.

security.txt on other platforms

Other fixes for A custom site

See the full fix-it matrix →

Prove your site is safe.

Once it is fixed, show it. Get a badge your shoppers can verify, backed by continuous checks. Free to start.

Get started free Run a free check