security.txt Generator
Four lines of text that tell a researcher who found a bug in your site where to send it. The file is trivial to write and easy to write wrongly, and both of the mistakes that matter are invisible: an Expires in the past makes the whole file formally stale, and a Canonical that does not match where the file is served makes it useless as proof it is yours. So this checks as it writes.
Where the file goes
https://example.com/.well-known/security.txt, served over HTTPS with
Content-Type: text/plain; charset=utf-8. That path is the one scanners and
researchers look at, and the only one that counts. A copy at /security.txt is
permitted as a legacy fallback; a copy anywhere else is not found.
One file per domain, and subdomains need their own. If your bug bounty covers
api.example.com too, that host needs the file at its own
/.well-known/ path.
The two required fields
Contact
At least one, and more than one is normal — an email address, a web form, and a phone number
cover different kinds of urgency. Each has to be a URI: mailto:,
tel: or https://. A bare [email protected] is the
commonest mistake in the wild and is flagged here, as is an http:// form, which
§2.5.3 forbids — asking someone to post a vulnerability report over plaintext is the wrong
first impression.
Order matters: list them in the order you would like to be contacted.
Expires
Required since the RFC, and the field most existing files are missing. It says how long the information should be considered current; past that date a scanner should treat the file as abandoned. Under a year is the recommendation, so the file gets looked at occasionally — a date in 2099 is technically valid and defeats the purpose, and this warns about it. A date already in the past is an error, because the file is stale the moment it is published.
Canonical, and why it is worth setting
Canonical is the URL this file is served from. It exists so a copy of your
security.txt found somewhere else — a mirror, a scraper, a phishing host — can
be told apart from the original: the canonical URL points back at your domain, and only you
control what is served there. It therefore has to end in
/.well-known/security.txt, which is checked here.
If you sign the file with PGP, the signature covers the canonical URL too, which is what makes the pair meaningful.
The optional fields
- Policy — your disclosure policy. What is in scope, what you promise, how long you take. The single most useful thing to add after Contact.
- Encryption — a link to a public key, not the key itself. An
https://URL, adns:URI, or anopenpgp4fpr:fingerprint. - Acknowledgments — where you credit reporters. Note the US spelling; the RFC uses it and a parser will not accept the other one.
- Preferred-Languages — language tags, comma separated, in no particular order of preference. It may appear only once.
- Hiring — the security roles you are recruiting for. It is in the spec, and it works.
- CSAF — a link to your CSAF provider metadata, if you publish machine-readable advisories.
Checking a file you already have
Paste it into the last box and the fields above are ignored. Every line is checked in place
and reported by line number: fields that are not Name: value, contacts that are
not URIs, an Expires that has passed, http:// where the RFC wants
https://, malformed language tags, and fields repeated that may appear only
once. Unknown field names are noted rather than failed — the format allows extensions, and a
parser will simply skip them.
Privacy
100% client-side. Nothing is uploaded, and no request is made to the domain you type.
Related tools
- robots.txt generator — the other file everyone expects at a well-known path.
- Sitemap generator — and the
Sitemap:line that goes in robots.txt. - URL privacy audit — what your URLs leak before anyone reports it.
- Mixed-content checker — the http:// resources on an https:// page.