security.txt File Template
A security.txt file template per RFC 9116 with all fields required or recommended for CRA Article 13 compliance. Includes explanations of each field, expiry date guidance, PGP signing instructions, and a CSAF advisory feed pointer. Covers the complete lifecycle from initial publication through ongoing maintenance.
What is security.txt?
Article 13(1)security.txt for [YOUR ORGANISATION NAME]
Published at: https://[YOUR-DOMAIN]/.well-known/security.txt
Standard: RFC 9116 (https://www.rfc-editor.org/rfc/rfc9116)
CRA Article 13 compliance: This file provides the single point of contact
for vulnerability disclosure as required by Article 13 of the EU
Cyber Resilience Act (Regulation (EU) 2024/2847).
Last updated: [DATE]
Maintained by: [SECURITY TEAM NAME / PSIRT]
security.txt is a plaintext file published at a well-known URL that tells security researchers how to report vulnerabilities to your organisation. RFC 9116 standardised the format in 2022. CRA Article 13 requires a 'single point of contact' for vulnerability reports — a security.txt file is the most widely adopted machine-readable way to publish that contact. The file must be placed at https://[your-domain]/.well-known/security.txt (the canonical location per RFC 9116). It may also be placed at https://[your-domain]/security.txt for backward compatibility.
Required Fields (Contact, Expires)
Article 13(1)-------------------------------------------------------
REQUIRED FIELDS
-------------------------------------------------------
Contact: The channel through which security researchers should report
vulnerabilities. Use HTTPS URLs for web forms, or mailto: for email.
You may list multiple Contact fields in order of preference.
Contact: https://[YOUR-DOMAIN]/security/report Contact: mailto:security@[YOUR-DOMAIN]
Expires: The date and time after which this security.txt file
should be considered stale and not relied upon. RFC 9116 requires
this field. Format: ISO 8601 (YYYY-MM-DDThh:mm:ssZ).
Best practice: set Expires to 12 months from publication date
and update it (along with any changed fields) before it expires.
An expired security.txt is treated by automated tools as if no
security.txt exists.
Expires: [YYYY-MM-DDT23:59:59Z]
The Contact and Expires fields are the only two fields required by RFC 9116. Everything else is recommended but optional. Set the Expires date to 12 months from publication and create a calendar reminder to renew it. An expired security.txt causes automated scanner tools to flag your organisation as having no disclosure contact — which affects your CRA compliance evidence.
Recommended Fields (Encryption, Acknowledgments, Policy, Hiring, CSAF)
Article 13, Annex I-------------------------------------------------------
RECOMMENDED FIELDS
-------------------------------------------------------
Encryption: A URL to a PGP public key that researchers can use to
encrypt sensitive vulnerability reports. Strongly recommended to
enable reporters to submit sensitive details confidentially.
The key should be available both at this URL and on a public keyserver.
Encryption: https://[YOUR-DOMAIN]/security/pgp-key.txt
Acknowledgments: A URL to a page where you credit security researchers
who have responsibly disclosed vulnerabilities to you.
This incentivises future reports and demonstrates community engagement.
Acknowledgments: https://[YOUR-DOMAIN]/security/hall-of-fame
Policy: A URL to your full CVD/vulnerability disclosure policy.
This is where researchers can read the detailed terms of your
coordinated disclosure process, safe harbour, and timelines.
Policy: https://[YOUR-DOMAIN]/security/vulnerability-disclosure-policy
Preferred-Languages: Languages in which you can receive and respond
to vulnerability reports. Use BCP 47 language tags.
Preferred-Languages: en, [de, fr, nl, es — add as applicable]
Hiring: A URL to your security job postings. Optional but can help
attract security talent who discover your security.txt.
Hiring: https://[YOUR-DOMAIN]/careers/security
CSAF: A URL to your CSAF (Common Security Advisory Framework) 2.0
provider metadata file. This enables automated tools to discover
and parse your security advisories. Recommended under CRA Annex I.
CSAF: https://[YOUR-DOMAIN]/.well-known/csaf/provider-metadata.json
Canonical: The authoritative URL of this security.txt file.
If you host the file at multiple locations, Canonical identifies
the primary one.
Canonical: https://[YOUR-DOMAIN]/.well-known/security.txt
The Encryption field is the most important recommended field — researchers with sensitive vulnerability details need a way to encrypt their report. If you do not have PGP set up, creating a key is straightforward and worth doing before publishing security.txt. The CSAF field is specifically relevant for CRA Annex I compliance and enables security tooling to automatically discover your advisory feed.
Complete Template with Placeholders
Article 13(1)-------------------------------------------------------
security.txt for [ORGANISATION NAME]
Publish at: https://[YOUR-DOMAIN]/.well-known/security.txt
RFC 9116: https://www.rfc-editor.org/rfc/rfc9116
-------------------------------------------------------
How to report a security vulnerability:
Contact: https://[YOUR-DOMAIN]/security/report Contact: mailto:security@[YOUR-DOMAIN]
Our full vulnerability disclosure policy:
Policy: https://[YOUR-DOMAIN]/security/vulnerability-disclosure-policy
PGP key for encrypting sensitive reports:
Encryption: https://[YOUR-DOMAIN]/security/pgp-key.txt
Researchers we have credited for past disclosures:
Acknowledgments: https://[YOUR-DOMAIN]/security/hall-of-fame
Languages we can respond in:
Preferred-Languages: en
Our CSAF 2.0 advisory feed:
CSAF: https://[YOUR-DOMAIN]/.well-known/csaf/provider-metadata.json
Security job openings:
Hiring: https://[YOUR-DOMAIN]/careers/security
Canonical URL of this file:
Canonical: https://[YOUR-DOMAIN]/.well-known/security.txt
This file expires on [DATE]. Please check for an updated version.
Expires: [YYYY-MM-DDT23:59:59Z]
-------------------------------------------------------
END OF security.txt
-------------------------------------------------------
Copy this complete template and replace all [PLACEHOLDER] values. The minimum viable security.txt requires only Contact and Expires — but publishing a minimal file misses the opportunity to give researchers everything they need to submit a high-quality report. Set up the full set of fields before publishing.
PGP Signing Instructions
-------------------------------------------------------
PGP-SIGNED security.txt — EXAMPLE
Per RFC 9116, a security.txt file may be digitally signed
using a PGP clear-text signature. This allows automated tools
and researchers to verify the file has not been tampered with.
-------------------------------------------------------
Step 1: Create your PGP key (if you do not already have one):
gpg --full-generate-key
Choose: RSA 4096-bit, no expiry (or 2-year expiry), email: security@[YOUR-DOMAIN]
Step 2: Export and publish your public key:
gpg --armor --export security@[YOUR-DOMAIN] > pgp-key.txt
Upload pgp-key.txt to https://[YOUR-DOMAIN]/security/pgp-key.txt
Upload to keyserver: gpg --keyserver hkps://keys.openpgp.org --send-keys [KEY-ID]
Step 3: Sign your security.txt file:
gpg --clearsign security.txt
This produces security.txt.asc — rename it to security.txt
The signed file will look like:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Contact: https://[YOUR-DOMAIN]/security/report Contact: mailto:security@[YOUR-DOMAIN] Policy: https://[YOUR-DOMAIN]/security/vulnerability-disclosure-policy Encryption: https://[YOUR-DOMAIN]/security/pgp-key.txt Acknowledgments: https://[YOUR-DOMAIN]/security/hall-of-fame Preferred-Languages: en CSAF: https://[YOUR-DOMAIN]/.well-known/csaf/provider-metadata.json Hiring: https://[YOUR-DOMAIN]/careers/security Canonical: https://[YOUR-DOMAIN]/.well-known/security.txt Expires: [YYYY-MM-DDT23:59:59Z]
-----BEGIN PGP SIGNATURE-----
[BASE64-ENCODED SIGNATURE WILL APPEAR HERE AFTER SIGNING] -----END PGP SIGNATURE-----
Step 4: Set the correct MIME type on your web server:
Content-Type: text/plain; charset=utf-8
Verify: curl -I https://[YOUR-DOMAIN]/.well-known/security.txt
PGP signing is not required by RFC 9116 but is strongly recommended. A signed security.txt provides evidence of authenticity — important if an attacker attempts to modify your security.txt to redirect researcher reports. The signing key should be the same key published in the Encryption field. Re-sign the file every time you update it, including when renewing the Expires date.
Keeping security.txt Current
Article 13(1)MAINTENANCE CHECKLIST FOR security.txt
Review this file at least every 12 months and whenever:
- Your security contact email address changes
- Your vulnerability disclosure portal URL changes
- Your CVD policy URL changes
- Your PGP key changes (rotate every 2-3 years)
- Your CSAF feed URL changes
- You launch a bug bounty programme
- You hire a new PSIRT Lead who should be the disclosure contact
EXPIRY RENEWAL PROCESS:
1. Update the Expires field to the new date (12 months from today)
2. Update any other changed fields
3. Re-sign the file with your PGP key
4. Deploy the updated file to https://[YOUR-DOMAIN]/.well-known/security.txt
5. Verify the file is accessible and correctly MIME-typed:
curl https://[YOUR-DOMAIN]/.well-known/security.txt
6. Verify PGP signature (if signed):
curl -s https://[YOUR-DOMAIN]/.well-known/security.txt | gpg --verify
MONITORING:
Consider adding a monitoring alert that fires 30 days before
the Expires date. An expired security.txt causes automated CRA
compliance checks to flag your organisation as non-compliant.
MULTI-DOMAIN ORGANISATIONS:
If your organisation has multiple domains (product domains, regional
domains, etc.), publish security.txt on each domain, or use the
Canonical field to point to a single authoritative file.
Example: https://[PRODUCT-DOMAIN]/.well-known/security.txt
pointing to Canonical: https://[MAIN-DOMAIN]/.well-known/security.txt
An expired or stale security.txt is one of the most common CRA Article 13 compliance failures. Automated compliance tools scan for security.txt presence and expiry. Create a calendar reminder 30 days before your Expires date and treat it with the same urgency as renewing a TLS certificate. Multi-domain organisations frequently publish security.txt on their main domain but forget product-specific or regional domains.
Verification
Article 13(1)VERIFICATION STEPS — confirm your security.txt is correctly deployed
1. File accessible at canonical URL:
curl -s https://[YOUR-DOMAIN]/.well-known/security.txt
Expected: plain text file with all your fields
2. Correct MIME type (text/plain):
curl -sI https://[YOUR-DOMAIN]/.well-known/security.txt | grep -i content-type
Expected: Content-Type: text/plain; charset=utf-8
3. HTTPS only (HTTP should redirect to HTTPS):
curl -sI http://[YOUR-DOMAIN]/.well-known/security.txt | grep -i location
Expected: Location: https://[YOUR-DOMAIN]/.well-known/security.txt
4. Expires field is in the future:
Check the Expires: field in the file — must be a future ISO 8601 date
5. PGP signature valid (if signed):
curl -s https://[YOUR-DOMAIN]/.well-known/security.txt | gpg --verify
Expected: Good signature from security@[YOUR-DOMAIN]
6. Use an online validator:
https://internet.nl (checks security.txt as part of web standards check)
https://securitytxt.org (dedicated security.txt checker)
7. CRA compliance tools:
CVD Portal verifies security.txt presence and validity as part of
CRA Article 13 compliance monitoring.
Verification should be performed immediately after publishing security.txt and after each update. The most common deployment errors are: wrong MIME type (returning text/html instead of text/plain), HTTP-only access without HTTPS redirect, and typos in email addresses or URLs that break automated parsing. The securitytxt.org validator catches most syntax errors before they affect researchers.
Use this template automatically in CVD Portal
CVD Portal generates your CVD policy, tracks acknowledgments, and creates an audit trail — free, forever.
Set up your free portal