The fix, in one snippet
Contact: Mailto:[email protected]
Expires: 2027-01-01T00:00:00.000Z
Preferred-Languages: En
Illustrative values. Change the paths, hostnames and options to match your own site before using it.
The sections below explain what is tested, why it matters and the alternatives.
What we test
Scan.now requests /.well-known/security.txt over HTTPS and, for information only, the legacy location /security.txt. A file found is parsed against RFC 9116: the required Contact: field (a mailto:, https: or tel: URI) and the required Expires: field (an ISO 8601 date-time). It flags an Expires date in the past, or more than a year ahead, which the RFC advises against, a Content-Type other than text/plain, a file that is only reachable over plain HTTP, and unknown field names. It notes the optional fields present (Encryption, Canonical, Policy, Preferred-Languages, Acknowledgments, Hiring) and whether the file carries a PGP signature. Absence is reported as informational; it is not a vulnerability, but it is the easiest security improvement on this page.
Why it matters
When someone finds a vulnerability in your site, what happens next depends on whether they can reach you. Without a published contact, reports go to whatever address the researcher can guess, get lost in a support queue, or never get sent, and the vulnerability stays open until someone less well-intentioned finds it. RFC 9116 standardised a machine-readable file at a fixed location so that researchers and automated tooling can find the right channel in seconds. The Expires field exists because stale contact details are worse than none; a file that says "reviewed within the last year" is a signal that someone is home. The practice has regulatory weight as well: CISA's Binding Operational Directive 20-01 requires US federal civilian agencies to publish a security.txt as part of their vulnerability disclosure policy. Scan.now's own file is at /security.
How to fix it
Create the file with the two required fields and the optional ones you can support. Dates are ISO 8601 with a timezone:
Contact: mailto:[email protected]
Contact: https://example.com/security/report
Expires: 2027-09-01T00:00:00.000Z
Preferred-Languages: en
Canonical: https://example.com/.well-known/security.txt
Policy: https://example.com/security/policy
Encryption: https://example.com/pgp-key.txt
Serve it as plain text over HTTPS. nginx:
location = /.well-known/security.txt {
default_type text/plain;
alias /var/www/site/security.txt;
}
Apache (the file simply lives at .well-known/security.txt under the document root; make sure any dotfile-blocking rule excludes .well-known):
<Files "security.txt">
ForceType text/plain
</Files>
Express: app.get('/.well-known/security.txt', (req, res) => res.type('text/plain').sendFile(path.join(__dirname, 'security.txt'))). Cloudflare offers a managed security.txt in the dashboard (Security > Settings) that is served at the edge. Put a calendar reminder a month before Expires; the generator at securitytxt.org produces a valid file if you would rather not type it.
Where this fits
security.txt (RFC 9116) present is check 14 of 14 that the website vulnerability scanner runs under exposed files and information disclosure, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.
Fix this one first
Above it in the same category sits robots.txt review (info), where a review of robots.txt. An attacker who has that does not need this, so it is the better use of the same hour.
Found in the same scan
The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and HTTPS is available, where the site could not be reached over HTTPS on port 443, or the TLS handshake failed. A single run of website vulnerability scanner answers all of them at once.
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.
Finding: security.txt (RFC 9116) present (info severity)
Scanner check id: security-txt
The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.
Sign in with GoogleSigning in is free and takes one click. We store your email address and nothing else.