News
security.txt Expires vs Stale Contact for Public Sites
September 15, 2025
security.txt Expires vs a stale Contact for public sites is a freshness decision versus an intake-mailbox decision: RFC 9116 requires an Expires timestamp so parsers know the file is still intended, while Contact is the URL or email researchers should use. A file with a future Expires and a mailbox nobody reads is worse than omitting security.txt. RoastMyOpsec does not require security.txt and does not score a missing or expired file as a standalone F.
The practical difference
RFC 9116 security.txt lives at /.well-known/security.txt. Contact and Expires are the core fields. Policy, Acknowledgments, Canonical, and Encryption are optional. Expires is not a certificate; it is how you promise the file is still current. After that date, consumers should treat the file as stale.
Stale Contact is the human failure: intern@, a departed employee, a Google Group that auto-expires, or a ticket form that 404s. Researchers who follow a dead Contact waste time or go public. humans.txt is not an alternate parser location. A /security HTML page can still help humans; the machine file still needs a live Contact.
Publishing security.txt is a commitment to read it. If legal will not let you, do not ship a decorative file with a personal Gmail and a two-year Expires.
How to choose based on what you shipped
If you will triaging reports: ship security.txt with a monitored alias, a realistic Expires you will renew, and Canonical if you mirror hosts. If you will not read reports: omit the file rather than lie. Do not put the only Contact in humans.txt or a blog RSS item.
| Option | When it wins | Watch-out | Takeaway |
|---|---|---|---|
| Fresh Expires + live Contact | You will actually read reports | Forgetting to renew Expires | This is a working disclosure file |
| Expired security.txt | It does not — parsers should ignore it | Leaving Contact that still looks official | Renew or remove |
| No security.txt | You will not staff an inbox | Researchers guessing webmaster@ | Honest empty state |
| HTML /security page only | You want human prose plus a form | Assuming parsers will scrape the HTML | Useful extra, not RFC 9116 |
When a public HTML contact page still wins
A human /security page still wins for policy prose and a form people can understand. The well-known file still wins for parsers. An expired file with a dead Contact wins nothing. Missing security.txt is not a roast F; a decorative stale file is a process miss.
Common mistakes
The first mistake is shipping Contact to a mailbox nobody monitors.
The second mistake is letting Expires lapse while leaving the file up as if it were current.
The third mistake is treating a missing security.txt as a RoastMyOpsec F.
What a URL roast can prove
RoastMyOpsec does not require security.txt and does not score Expires, Contact, JSON-LD, or Open Graph as standalone Fs. The free roast is headers, TLS, cookies, bounded paths (.git/HEAD, .env, package.json signatures), and js-secrets on a consented URL. If you publish RFC 9116, keep Expires honest and Contact staffed; confirm the file yourself.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Is Expires required in security.txt?
- Yes. RFC 9116 requires Expires so consumers can tell whether the file is still intended to be current.
- Is a missing security.txt a vulnerability?
- No. It is a missed intake channel if you wanted one. It is not a roast F.
- Can humans.txt hold the security mailbox instead?
- You can mention people there, but parsers look at /.well-known/security.txt. Put Contact in the RFC 9116 file.