A vulnerability can be discovered before your monitoring detects it. When that happens, the person who found it needs a reliable way to reach the team that can investigate. If the only visible contact is a general support form, an abandoned mailbox, or a guessed employee address, a useful report can be delayed or lost.
security.txt addresses this narrow problem. It is a machine-readable text file published at a well-known HTTPS location so a researcher can discover your vulnerability-reporting contact and related disclosure information without guessing.
The file does not make a service less vulnerable, validate incoming reports, or replace a vulnerability-response process. Its value is simpler: it reduces uncertainty about where a security report should go. This article explains the trust model behind security.txt, the smallest useful file, how to operate it reliably, and what the control cannot do for you.
Treat report routing as part of vulnerability response
Imagine a researcher notices a security flaw in app.example.com. The technical finding may be clear, but the reporting path is not:
finding
|
+--> support form?
+--> webmaster?
+--> security@example.com?
+--> public issue tracker?Every uncertain branch adds a chance that sensitive details reach the wrong audience or that nobody responsible sees them promptly.
A published security.txt changes the discovery path:
finding
|
v
https://app.example.com/.well-known/security.txt
|
v
published reporting contact and policyThis is a routing control, not an authorization control. The publisher states where vulnerability reports should be sent. A researcher still has to decide whether the published information is trustworthy, and your organization still has to receive, triage, investigate, and remediate the report.
The threat and failure model therefore includes ordinary operational mistakes as well as malicious interference. You want to reduce lost reports, stale contacts, accidental disclosure to unrelated channels, and ambiguity about the intended reporting route. You also need to consider an attacker who has compromised the website and can alter the file or redirect researchers elsewhere.
security.txt does not protect against compromise of the application, stop fraudulent reports, prove that a reporter is trustworthy, or guarantee that your team responds. It makes one boundary explicit: the public service publishes a discoverable route into the organization’s vulnerability-response process.
Start with the smallest useful file
RFC 9116 defines the security.txt format. For web services, the current location is:
https://example.com/.well-known/security.txtA minimal teaching example can be as small as:
Contact: mailto:security@example.com
Expires: 2027-03-01T00:00:00ZTwo details matter immediately.
Contact tells the researcher how to report a vulnerability. The field is required and may appear more than once. Its value is a URI, so an email contact uses the mailto: scheme rather than a bare email address. If you publish several contacts, RFC 9116 says to list them in order of preference.
Expires tells the researcher when the information should be considered stale. It is also required, appears once, and uses an RFC 3339 date-time. The RFC recommends setting it less than a year into the future so forgotten contact information does not look indefinitely current.
The example is intentionally small. A production file often benefits from more context, but adding fields is useful only when the referenced resources are real, maintained, and understood by the people operating them.
Add context without hiding the reporting route
A practical file might look like this:
Contact: mailto:security@example.com
Policy: https://example.com/security-policy
Preferred-Languages: en
Canonical: https://example.com/.well-known/security.txt
Expires: 2027-03-01T00:00:00ZEach addition answers a different question.
Policy can point to a page describing your vulnerability-disclosure process, such as what systems are in scope, what information helps triage, and what a reporter can expect after submission. The contact should still be usable without requiring the researcher to infer an address from that page.
Preferred-Languages communicates which languages the organization prefers for reports. This can reduce avoidable communication friction, but it should reflect languages your response process can actually support.
Canonical identifies the location where the file is intended to live. When a Canonical field is present, RFC 9116 says that a file retrieved from a URI not listed by any Canonical field should not be trusted. This makes the file’s intended location explicit, but it is not independent proof of authenticity: an attacker able to replace both the file and its contents can replace the Canonical value too.
That distinction is important. A field inside a document can describe the document’s intended identity. It cannot, by itself, prove that an uncompromised party authored the document.
Understand the domain boundary
A common operational mistake is assuming one security.txt automatically covers an entire DNS hierarchy.
Under RFC 9116, a file applies to the domain or IP address from which it was retrieved; it does not automatically apply to parent domains or subdomains. If you operate both example.com and api.example.com, publishing the file only on example.com does not make it the RFC-defined security.txt for api.example.com.
That leads to a practical inventory question: which public host names might a researcher investigate independently?
For a small service, publishing the same maintained file on each relevant host may be enough. A larger organization may centralize the policy and contact destination while still ensuring that each relevant host exposes a valid /.well-known/security.txt. The exact deployment depends on your routing architecture, but the trust boundary should remain clear to the reader of the file.
The file must be retrieved over HTTPS and served as UTF-8 text/plain. A legacy top-level /security.txt can exist for compatibility, but RFC 9116 gives precedence to the file under /.well-known/ when both are present.
Make the contact operational, not merely syntactically valid
A perfect file pointing to an unattended mailbox is a failed control.
The contact destination should be owned as an operational service. Decide who monitors it, who provides backup coverage, how reports enter the team’s triage workflow, and what happens when the primary responder is unavailable. If the contact forwards mail, test the complete path rather than only checking that the address exists.
A useful verification exercise is deliberately boring:
public Internet
|
+--> fetch /.well-known/security.txt
|
+--> use the published Contact
|
+--> confirm receipt in the real triage queueRun that test from outside the production network. It catches problems such as a route available only internally, a mailbox rejected by an email gateway, a stale policy URL, an unexpected redirect, or a deployment that serves the file on one host but not another.
Do not put credentials, internal escalation addresses, private infrastructure details, or secrets in the file. It is intentionally public. Publish the route a reporter needs, then keep internal assignment and escalation inside your response process.
Treat expiration as a maintenance trigger
Expires is useful only if someone owns renewal.
Do not solve expiration by choosing a date many years away. That removes the signal that the contact information needs periodic review. RFC 9116 specifically recommends an expiry less than a year in the future.
Instead, make renewal a small operational check. Before advancing the date, verify that:
- every published contact still reaches the intended team;
- every linked policy or encryption resource still exists and is controlled by the organization;
- the file is present on the public hosts it is meant to cover;
- HTTPS retrieval works without an unexpected destination change;
- the content still describes the actual disclosure process.
The expiry date is not a certificate lifetime and does not cryptographically revoke old content. It tells consumers when the published information should be treated as stale. Your deployment and monitoring must ensure the current file is actually available.
Consider tampering separately from availability
A researcher usually retrieves security.txt from the same web presence they are investigating. This creates an important limitation: if an attacker compromises that presence deeply enough, they may be able to replace the file or redirect requests to a contact they control.
HTTPS protects the connection under the usual TLS trust assumptions, but it does not protect a file from an attacker who controls the legitimate server or deployment credentials.
RFC 9116 recommends OpenPGP cleartext signing of security.txt as an additional authenticity mechanism. A signature can help only if the researcher can establish trust in the signing key independently. Signing a file and publishing an unverified key beside it on the same compromised system does not create an independent trust anchor.
This is a good example of defense in depth. A small organization may reasonably begin with a correct HTTPS deployment, a monitored contact, short maintenance intervals, and external availability checks. An organization with a mature vulnerability-disclosure program and a credible way to distribute or establish trust in a signing key can add signatures for stronger tamper detection.
In either case, monitor the public file itself. A health check that only confirms HTTP status 200 is weaker than one that also verifies the expected contact, canonical location, expiry window, and important referenced URLs.
Keep vulnerability reports separate from incident reporting
security.txt is designed to aid vulnerability disclosure: someone has found a weakness in a product or service and needs to tell the responsible organization.
That is not automatically the same workflow as reporting an active account compromise, fraud event, abusive content, or production outage. Those cases may require different identity checks, evidence handling, urgency, or support access.
Avoid turning security.txt into a directory of every operational contact. A narrow vulnerability-reporting route is easier for researchers to understand and easier for your team to own. If your policy needs to direct other incident types elsewhere, make that distinction explicit on the linked policy page.
Avoid the failure modes that defeat the control
Most security.txt failures are not complicated protocol failures. They are mismatches between published information and operational reality.
A guessed address such as security@example.com is not a substitute for a configured, monitored address. A policy page is not useful if it requires authentication from external reporters. An expired file tells careful consumers that the data is stale. A contact that routes into a general support queue can expose vulnerability details to more people than necessary and delay technical triage.
Another mistake is publishing a file once and treating the task as complete. Teams reorganize, domains move, mail systems change, and disclosure policies evolve. The control remains useful only while the public file and the internal response path agree.
Finally, do not interpret publication as a promise that every submission is valid. The receiving process still needs normal defensive handling: treat report content and attachments as untrusted input, avoid running supplied code merely because it arrived through the security channel, preserve relevant evidence, and verify findings before changing production systems.
Use security.txt as the front door, not the whole process
For an Internet-facing service, security.txt is a small control with a clear job: make the intended vulnerability-reporting path discoverable and machine-readable.
Publish it at /.well-known/security.txt over HTTPS. Provide a real Contact and a maintained Expires value. Add policy, language, canonical, or encryption information when those fields correspond to services you genuinely operate. Test the route from the public Internet, assign ownership for renewal, and monitor for unexpected changes.
Then keep the boundary clear. security.txt helps a report reach you; it does not triage the report, authenticate the reporter, remediate the vulnerability, or prove its own integrity after the hosting environment is compromised. Those responsibilities belong to the wider vulnerability-management and incident-response system.