Security.txt RFC 9116 for NZ sites: /.well-known/security.txt file format and vulnerability disclosure

Quick answer

security.txt is a small, plain-text file you publish at https://yoursite.nz/.well-known/security.txt so security researchers know how to reach you when they find a vulnerability. It is defined in RFC 9116, it is recommended rather than mandatory, and the file itself is two to ten lines long. The minimum useful content is one Contact line (an email address or a URL) and one Expires line (a date roughly a year in the future). Anything beyond that is optional.

If your scanner flags sec_txt as missing, the Free Website Security Check tells you which directive to add and where to put it.

What security.txt actually does

The basic idea behind security.txt is the same as a robots.txt or a humans.txt: it is a standard, well-known location where a website publishes structured information for a specific audience. For robots.txt, that audience is web crawlers. For humans.txt, it is curious humans. For security.txt, the audience is security researchers — and the file tells them how to report a vulnerability to you (1).

The file lives at a fixed URL:

https://yoursite.nz/.well-known/security.txt

The .well-known prefix is reserved by RFC 8615 for exactly this kind of site-wide metadata. Visiting that URL in a browser should return a plain-text file with Content-Type: text/plain. Researchers, automated scanners, and bug-bounty platforms all know to look there.

security.txt is a way of saying "if you find something wrong with our site, here's how to tell us instead of telling the world." For most New Zealand schools and small businesses, just having it there — even with only a contact email — is enough to look credible and to give well-meaning researchers a path in.

Why security.txt matters for NZ sites

Three reasons it sits in the NZAI baseline rather than being filed under "nice to have":

  • It redirects opportunistic disclosures. A researcher who finds a vulnerability has three realistic options: tell nobody, tell the world, or tell you. security.txt makes the third option the obvious one — and the only one with a published contact path. CERT NZ explicitly recommends publishing contact information as part of baseline organisational hygiene (2).
  • It shortens the time-to-fix. When a vulnerability is reported, every hour of delay is an hour the bug is in the wild. A published contact means a researcher can reach the right person (or the right inbox) in seconds rather than guessing an email address or DM'ing a random staff member on social media.
  • It is the de facto standard. Tools like Mozilla Observatory, the NCSC scanner family, and several CERT-style national platforms all check for the presence and freshness of security.txt. A scanner that flags sec_txt as missing is reporting a gap that other security tooling will also flag.

For the broader educator safety pathway, including account security, devices, phishing, and student data, see Building Cyber-Safe Habits as an NZ Educator.

What goes in security.txt

RFC 9116 defines a small set of directives. Each is a single line of key: value text. Here is the canonical minimum:

# NZAI Security — security.txt
# RFC 9116 — https://www.rfc-editor.org/rfc/rfc9116.html

Contact: mailto:security@yourschool.nz
Contact: https://forms.yourschool.nz/security-report
Expires: 2027-09-20T12:00:00.000Z
Preferred-Languages: en-NZ, en
Canonical: https://yourschool.nz/.well-known/security.txt

Walking through each line:

  • Contact: — required. The address researchers use to report a vulnerability. Can be repeated. Most common forms are mailto:security@yourschool.nz (email) and a https://forms.yourschool.nz/security-report URL (web form). Pick whichever you can guarantee gets read.
  • Expires: — required. The date and time the file stops being valid. After this date, scanners and researchers should treat the file as stale and ignore the contact details (1). A year from the publication date is conventional.
  • Preferred-Languages: — optional but recommended for NZ sites. Lists the languages you would prefer reports in. en-NZ, en is fine for almost every NZ organisation.
  • Canonical: — optional. The fully-qualified URL where the canonical file lives. Helps when you serve the same file at multiple paths (e.g. behind a CDN or a www→apex redirect).

What does NOT go in security.txt

The RFC is explicit about a few "do nots" and there are also some real-world pitfalls worth flagging:

  • Do not put a PGP key directly in the file. Use the Encryption: directive with a URL where researchers can fetch your key, instead of pasting the whole key into the file. A security.txt file with a 4KB PGP block in it is harder to maintain and easier to corrupt (1).
  • Do not put personal mobile numbers. Use a role address (security@, it-admin@) or a shared inbox. Staff move on; the file should not move with them.
  • Do not put an office street address. It is not what researchers need, and it is information you do not need to publish.
  • Do not advertise bug-bounty reward amounts in the file. That belongs in your public bug-bounty policy, not in the standards-track RFC 9116 file.
  • Do not forget to refresh Expires. A security.txt that has expired is worse than no file at all: it tells scanners you used to take reports seriously, and now look like you have stopped. Set a calendar reminder for one month before expiry.
  • Do not block the path with robots.txt or HTTP auth. Researchers, scanners, and the RFC all expect the file to be reachable as plain text without authentication.
The single most common security.txt mistake in the wild is forgetting to update Expires. Pick a date one year out, set a calendar reminder four weeks before, and re-publish. The whole file should be rotated at least once a year — and more often if the Contact or Encryption details change.

Copy-paste examples for the common stacks

Below are minimal, tested snippets for the four stacks most New Zealand schools and small businesses run on.

Static file (the most common approach)

For a static site, the simplest thing is to upload a literal security.txt to your /.well-known/ directory and serve it with Content-Type: text/plain. Many static site generators handle .well-known paths correctly. If yours does not, the nginx/Apache snippets below sort it out at the server level.

nginx

location = /.well-known/security.txt {
    default_type text/plain;
    add_header Cache-Control "max-age=3600, public";
    return 200 "# NZAI Security — security.txt\nContact: mailto:security@yourschool.nz\nContact: https://forms.yourschool.nz/security-report\nExpires: 2027-09-20T12:00:00.000Z\nPreferred-Languages: en-NZ, en\nCanonical: https://yourschool.nz/.well-known/security.txt\n";
}

Reload with nginx -s reload (or sudo systemctl reload nginx on systemd hosts).

Apache

Add inside your <VirtualHost>, or in an .htaccess in the document root:

<IfModule mod_alias.c>
    RedirectMatch 302 ^/\.well-known/security\.txt$ /security.txt
</IfModule>

Then place a literal security.txt file at the document root with the content shown above. Make sure it returns Content-Type: text/plain — Apache's mod_mime usually picks this up by file extension, but if the wrong type is served, the file is not standards-compliant.

Express (Node.js)

import express from 'express';
const app = express();

app.get('/.well-known/security.txt', (_req, res) => {
  res.type('text/plain').send(`# security.txt — RFC 9116
Contact: mailto:security@yourschool.nz
Contact: https://forms.yourschool.nz/security-report
Expires: 2027-09-20T12:00:00.000Z
Preferred-Languages: en-NZ, en
Canonical: https://yourschool.nz/.well-known/security.txt
`);
});

WordPress

Create a page or a file at /.well-known/security.txt. The cleanest way on a stock WordPress install is to drop a literal security.txt file in the document root (next to wp-config.php) — WordPress will serve it before its rewrite rules kick in. If your .htaccess redirects the path, use the Apache snippet above instead.

For the broader WordPress security baseline (file permissions, login lockdown, exposed wp-config), see the Web Server Hardening guide.

Security.txt RFC 9116 for NZ sites — /.well-known/security.txt file content and responsible disclosure contact

Optional directives worth knowing

A few additional RFC 9116 directives appear in real-world security.txt files. None of them are required, but they can help:

  • Encryption: — URL where researchers can fetch your PGP public key. Use this rather than embedding the key in the file directly (1).
  • Acknowledgments: — URL of a thank-you page where you publicly credit researchers who have reported issues. Useful for bug-bounty programmes, less so for schools.
  • Hiring: — URL of a security-jobs page. Strictly optional; leave it off if you are not hiring.
  • Policy: — URL of your full responsible-disclosure policy. Worth adding once you have written one.
  • Hiring: and Policy: are both single-line directives and follow the same key: value shape as everything else.

How to verify your security.txt

Two reliable ways, in order of speed.

1. Run the free NZAI scanner

The Free Website Security Check flags sec_txt as missing if your site has no /.well-known/security.txt, or reports it as present if it does. Run it after every change.

2. curl from the command line

curl -sI https://yourschool.nz/.well-known/security.txt

You should see HTTP/2 200, Content-Type: text/plain, and the body should start with # or Contact:. Then:

curl -s https://yourschool.nz/.well-known/security.txt

prints the file. Verify the Expires: date is in the future and that the Contact: address is one you still monitor.

Common security.txt mistakes to avoid

From running the free scanner across New Zealand school and small-business sites, the most frequent missteps are:

  • No file at all. The single most common finding. Even a one-line file with just Contact: and Expires: is better than nothing.
  • Expired Expires: date. A security.txt with Expires: 2024-01-01 is treated as stale by most tooling and ignored. Set the date one year out and refresh annually (1).
  • Wrong content type. Returning the file as text/html or application/octet-stream makes scanners and researchers skip it. It must be text/plain.
  • File behind authentication. A security.txt that requires a login is not standards-compliant. The whole point is that anyone can fetch it (1).
  • Personal contact details. Putting a personal email or mobile number in the file makes staff turnover a security incident. Use a role address or a shared inbox.
  • Redirect chain on the file. A security.txt that lives behind a www→apex redirect, a CDN, or a multi-hop rewrite can fail to parse in some clients. For redirect hygiene that keeps this file clean, see the Redirect Chains guide.

Knowledge check

Test your understanding of security.txt and RFC 9116 with these questions. Click or tap each card to flip it and see the answer.

Q1Your school runs a public website at https://mangawhai.school.nz. A security researcher emails the principal's PA to report a vulnerability they found. The principal has never heard of security.txt. What file should your IT admin publish, at what URL, and what minimum content should it contain?tap to flip
Answer: Publish a plain-text file at https://mangawhai.school.nz/.well-known/security.txt with at least two directives: Contact: (an email address or web form URL the researcher should use) and Expires: (a date roughly a year in the future). The file must be served as Content-Type: text/plain and must be reachable without authentication. The full directive list is in RFC 9116 (1).
Q2You publish a security.txt in January 2026 with Expires: 2027-01-01. In March 2027, the file is still online and unchanged. A scanner flags it as sec_txt: stale. What is the simplest fix?tap to flip
Answer: Update the Expires: value to a date roughly a year in the future (e.g. Expires: 2028-03-15T12:00:00.000Z) and re-publish the file. While you are there, double-check the Contact: is still an address you monitor. A stale Expires is the single most common reason a security.txt is ignored by tooling (1).
Q3Your IT team pastes the school's PGP public key directly into the security.txt file as a multi-line block. The scanner now reports the file is "malformed" and the security contact is "unreachable". What went wrong, and what is the right pattern?tap to flip
Answer: RFC 9116 specifies that security.txt is a flat list of single-line key: value directives. Embedding a PGP key (which is multi-line and contains colons and dashes that look like directive markers) breaks the parser. The right pattern is to publish your PGP key at a stable URL and reference it with the Encryption: directive — for example Encryption: https://yourschool.nz/.well-known/pgp-key.asc. Researchers fetch the key from the URL, not from the security.txt file itself (1).

Sources and references

[1] Internet Engineering Task Force. (2022). RFC 9116 — A File Format to Aid in Security Vulnerability Disclosure. https://www.rfc-editor.org/rfc/rfc9116.html

[2] CERT NZ. (2025). Reporting an issue to CERT NZ. https://www.cert.govt.nz/

[3] Internet Engineering Task Force. (2019). RFC 8615 — Well-Known Uniform Resource Identifiers (URIs). https://www.rfc-editor.org/rfc/rfc8615.html

[4] National Cyber Security Centre. (2025). Vulnerability disclosure guidance. https://www.ncsc.govt.nz/

[5] Mozilla. (2025). Security.txt file format guidance. https://developer.mozilla.org/en-US/docs/Web/Security/security.txt

[6] New Zealand. Parliament. (2020). Privacy Act 2020. https://www.legislation.govt.nz/act/public/2020/0031/latest/whole.html

What to do next