← All articles

SaaS

security.txt and a disclosure policy for a small SaaS: the free page that catches what a yearly test misses

November 13, 2026

The RFC 9116 security.txt file (only Contact and Expires are required), a one-page disclosure policy with safe-harbour wording, the six beg-bounty claims and a reply for each, inbox numbers from the Pentagon, CISA and curl programs (curl's valid rate fell from over 15% to under 5%), and why a managed bounty costs 3.5 to 10 times a yearly penetration test.

A rusty padlock hanging on a weathered wooden door

Sooner or later a stranger finds something on your site. Maybe a real hole, maybe a missing header they will email you about at 3 a.m. with the subject line "URGENT: critical vulnerability". Either way, they look for one thing first: where do I send this? If the answer is nowhere, they guess an address, post it publicly, or skip you.

A yearly penetration test shows you what one tester found in one week. A disclosure page catches what the other 51 weeks of strangers find. It costs an afternoon and no money. This article is that afternoon: the short security.txt file, a one-page policy with safe-harbour wording, what the junk emails look like and how to answer them, how big the inbox gets on public programs (with numbers), and when a paid bounty is worth it compared with a yearly test.

If you are asked about this on a customer's security questionnaire, this is also the cheap, honest "yes" for the vulnerability-reporting row. We cover the rest of that sheet in what a five-person vendor can honestly answer on a security questionnaire.

The short version

- Publish https://yourdomain/.well-known/security.txt with two required fields: Contact and Expires. Add Policy and Preferred-Languages and you are done.

- Publish a one-page policy at a stable URL: what is in scope, what is off limits, how fast you reply, and a promise not to take legal action against good-faith reporters.

- Send the mailbox to a shared address (security@) that at least two people read. One person on holiday is how a real report sits for three weeks.

- Expect junk. Most of it is the same six claims (missing SPF, no clickjacking header, and so on). Use a canned reply, do not pay, and fix the ones that are real.

- Skip a paid bounty until you have had at least two real tests and someone who can spend a day a week on triage. The numbers are below.

security.txt: what RFC 9116 actually requires

security.txt is an IETF standard, RFC 9116, published in April 2022 by E. Foudil and Y. Shafranovich. It is a plain text file at a fixed address so a researcher (or a scanner) knows where to send a report without guessing. Only two fields are required.

text
Field                Required?  What it does                                     Rule from the RFC
-------------------  ---------  -----------------------------------------------  ------------------------------------------
Contact              Yes        Where to report: mailto:, https:// or tel:       Listed in order of preference; web URIs
                                                                                    must be https; may repeat
Expires              Yes        Date after which the file is stale (RFC 3339)    Appear once; recommended less than 1 year
                                                                                    ahead
Policy               No         Link to your disclosure policy                   https only
Preferred-Languages  No         Language tags, e.g. en                           Once; English assumed if absent
Encryption           No         URL to your OpenPGP public key                   Never paste the key into the file
Acknowledgments      No         Page thanking researchers                        Spelled without the e: "Acknowledgments"
Canonical            No         The URL(s) this file is meant to live at         If the URL it was fetched from is not
                                                                                    listed, readers should not trust it
Hiring               No         Link to security jobs                            https only

The rules for serving it, from sections 2 and 3: the path is /.well-known/security.txt (a copy at /security.txt is allowed for older tools, and the /.well-known/ copy wins if both exist); it must be served over HTTPS as text/plain; charset=utf-8; lines can end in LF or CRLF; lines starting with # are comments; and a file signed with an OpenPGP cleartext signature is recommended but not required.

A complete file for a small SaaS:

text
# Security contact for example.com
Contact: mailto:security@example.com
Contact: https://example.com/security/report
Expires: 2027-10-31T23:59:00.000Z
Preferred-Languages: en
Policy: https://example.com/security
Canonical: https://example.com/.well-known/security.txt
Acknowledgments: https://example.com/security/thanks

To check it from a terminal:

bash
curl -sI https://example.com/.well-known/security.txt | grep -i -E "^(HTTP|content-type)"
# expect:  HTTP/2 200   and   content-type: text/plain; charset=utf-8
curl -s https://example.com/.well-known/security.txt | grep -i -E "^(contact|expires)"

How other people get it wrong (and how to avoid it)

A scan of the top one million domains by URIports (published 24 January 2025, comparing against April 2024) found how rare and how sloppy the files are:

text
Measure (top 1,000,000 domains)                             Result
----------------------------------------------------------  ----------------------
Domains with a security.txt                                 1.25% (12,510); was 0.7% (6,816)
Files that meet the RFC                                     44%
Contact is an email / a URL / a phone number                74% / 35% / 2%   (files can list several)
No Expires date at all                                      45%
Expires already in the past                                 13%
Expires more than a year away                               20%
Expires in an invalid format                                5%
Canonical URL does not match where the file was served      26%
Unknown field names                                         11%
"Acknowledgements" instead of "Acknowledgments"             10%
Wrong Content-Type                                          3.5%
Digitally signed                                            11% (half of those validated)

Three habits fix most of that list:

- Set Expires to about 11 months out and put a calendar reminder at 10. A file that expired in March says "nobody here reads this" more loudly than having no file. 13% of the million domains have exactly that.

- Copy the example above, then change only the values. Do not invent field names. The most common typo is the British spelling of Acknowledgments.

- Serve it from the real domain, not just a marketing subdomain. Researchers look at the domain in the URL bar of the product.

Signing is optional and only half of signed files verify. For a small company a clean, current, unsigned file beats a signed file nobody renewed.

The one-page disclosure policy

The Policy link is where the real value is. A one-page policy answers four questions for the person about to hit send: where does this apply, what must I not do, how long until you answer, and will you come after me. The UK National Cyber Security Centre's Vulnerability Disclosure Toolkit and the disclose.io project both publish templates; the UK toolkit is built around three parts (a way to communicate, a policy, and security.txt), which is the same shape as this article.

Here is a one-page version a small SaaS can adapt. It is our wording, not legal advice, so have whoever does your contracts look at the safe-harbour paragraph once.

text
Reporting a security problem to Example Ltd

If you think you have found a security problem in example.com or the
Example app, please tell us at security@example.com. We would rather hear
from you than not.

What is in scope
- example.com, app.example.com and api.example.com
- the Example mobile apps
Not in scope: our suppliers' systems (report those to the supplier),
social engineering of our staff, physical attacks, denial of service.

Please do not
- access, change or keep more customer data than needed to show the problem
- run automated scanners at high volume against production
- test with accounts you do not own
- tell others about the problem until we have fixed it or 90 days have passed

What you can expect from us
- an acknowledgment within 3 working days
- a first answer on whether we think it is a valid issue within 10 working days
- updates at least every 14 days until it is fixed
- credit on our thanks page if you want it
We do not run a paid bounty. We say thank you, and we may send a small gift.

Safe harbour
If you follow this policy and act in good faith, we will not start legal
action against you and we will not ask law enforcement to investigate you
for the research. If a third party starts action over research that followed
this policy, we will say publicly that it was authorised.
This does not cover extortion, or demanding payment before disclosing.

Last updated: 2026-11-14

Why each part is there:

- Scope list. It is what lets you say "that is out of scope" later without sounding rude. Include everything you run, name the things you do not (your payment processor, your host).

- "Please do not" list. This is the line between research and a breach. It also gives you something to point to if someone downloads your customer table to prove a point.

- Response times. Three working days to acknowledge is a promise a company of five can keep. Do not copy a large program's 24 hours if nobody watches the inbox at weekends. These specific numbers are our recommendation, not a standard.

- 90 days. A common norm in the research community. Say it yourself or someone will pick a shorter deadline for you.

- No bounty. Say it up front. It saves every researcher a question and lets you offer thanks instead.

Safe harbour: what the wording can and cannot do

Safe harbour is you saying, in writing, that you consider testing under your policy to be authorised. The legal backdrop in the US:

- On 19 May 2022 the Department of Justice changed its Computer Fraud and Abuse Act charging policy so that good-faith security research should not be charged. The policy defines it as accessing a computer solely to test, investigate or correct a security flaw, done in a way that avoids harm, with the results used mainly to improve security.

- That is internal DOJ guidance, not a statute. It does not bind courts or private parties, so a company could still sue. Commentators also point to the word "solely" as a gap: mixed motives leave discretion with the prosecutor.

- Extortion is outside it. DOJ said that discovering holes to extort owners is not good-faith research, and that a "research" label alone is not a free pass.

- The same policy limits prosecutions based only on terms-of-service breaches, after the Supreme Court's decision in Van Buren v. United States (2021).

So your policy matters in one more way: it is the document that shows you authorised the testing. Your terms of service probably forbid probing the site; the policy is the exception you wrote on purpose. Two things to avoid: promising what you cannot control ("we will protect you from all legal action" when your hosting provider or a customer may act on their own), and vague language like "white hat" that nobody can test.

The disclose.io project describes safe harbour as letting people "acting in good faith, as the recipient defines it" report issues without fear of legal repercussions. Its open-source policy generator is a reasonable starting point if you want a second draft to compare against.

The junk email: what a beg bounty looks like

Once your address is in a security.txt (and your domain is anywhere in a scan), you will get some beg bounties: unsolicited "reports" of trivial or non-existent issues from people who want a reward. Troy Hunt wrote about them in November 2021: they go to sites that have no published bounty, the details are held back until money is promised, and the issues claimed are things like DMARC records or a missing Content Security Policy header. Sophos described them as "scaremongering for profit".

A composite of the usual shape (we made this up from the patterns above, it is not a quote of one sender):

text
Subject: Security vulnerability found on your website - please respond

Dear Sir/Madam,
I am a security researcher. I found a critical vulnerability on your site
that lets an attacker send emails pretending to be you (spoofing).
Please tell me your bug bounty programme so I can send full details.
I look forward to a reward.
Regards

The six claims you will see most, what is usually true and how to check in a minute:

text
Claim                          Usually                                       Check
-----------------------------  --------------------------------------------  --------------------------------------
"No SPF / DMARC record"        Wrong (they used a web tool on the wrong      dig +short TXT example.com
                               name) or true but low severity                 dig +short TXT _dmarc.example.com
"Clickjacking possible"        True when no frame header is set; low         curl -sI https://example.com |
                               severity if the page has no sensitive action     grep -i -E "x-frame|frame-ancestors"
"Missing security headers"     True for HSTS/CSP; affects hardening only     curl -sI https://example.com
"Weak TLS / old protocol"      Often a scanner reading an old config         openssl s_client -tls1 -connect
                                                                             example.com:443  (should fail)
"Email spoofing"               Same as the SPF claim                         See our SPF, DKIM and DMARC article
"Exposed admin / server        A login page being visible is not a hole      Try it logged out; does it show data?
 banner / version"             unless it shows data or accepts weak logins

Two of these are covered in more depth in SPF, DKIM and DMARC for a ten-person business, which is also worth doing before the first email arrives. A missing DMARC policy is a real finding, just not a payable one.

How to answer. Wait until the next day, check the claim yourself, and then send one of these. The first is for something real and low, the second for demands:

text
Hello,
Thanks for getting in touch. We looked at the points in your email.
- SPF: record present at example.com (checked 14 Nov).
- DMARC: p=quarantine, set since 2025.
- Clickjacking: noted, we will add frame-ancestors this month.
We do not run a paid bounty, but we will credit you on
https://example.com/security/thanks if you would like that.
Our policy is at https://example.com/security. If you have a
reproducible issue with a proof of concept, please send it there.
text
Hello,
We do not pay for reports of missing headers or DNS settings and we have no
bounty programme. If you hold a specific vulnerability, send the steps to
reproduce under our policy at https://example.com/security. We will not
respond to requests for payment before disclosure.

The rules behind the replies: do not pay for non-issues (it brings more of them), do not argue, do not threaten legal action over an email, and if the tone turns into threats, keep the messages and report them to the police or your national cybercrime reporting site. Hunt's own rule after 100+ disclosures: never ask for money, and never pay one.

One caution that costs nothing. Now and then one of these has a real kernel inside (an exposed backup file, a leaked key in a public repo). Check each before closing it. The ten minutes spent on a false alarm is cheaper than the one you ignore.

How big does the inbox get? Numbers from public programs

Your inbox will be far smaller than any of these, but they show the pattern: most programs get a lot of reports and the share that is valid depends a lot on whether money is attached.

text
Program                                   Period            Reports                        Valid / actionable
----------------------------------------  ----------------  -----------------------------  ---------------------------
US Dept of Defense VDP (no payment)       Nov 2016 - 2022   ~45,000 from ~4,000 people     25,000+ actionable (56%),
                                                                                              6,000+ mitigated
US Dept of Defense VDP                    To Nov 2021       36,000+ from 3,000+ people     ~70% validated
US Dept of Defense VDP                    To March 2024     50,000th report, 5,635 people  (valid share not restated)
CISA federal agencies VDP platform        2022              40 agencies onboarded          1,330+ unique valid reports,
                                                                                              ~85% remediated
curl (paid bounty on HackerOne)           Apr 2019 -        2 reports a week by mid-2025   87 confirmed in seven years;
                                          Jan 2026                                          15%+ valid before 2025,
                                                                                              under 5% in 2025

What to take from it:

- A VDP with no money gets mostly honest reports. The DoD figures (over half actionable, about 70% validated in 2021) are what a no-payment program looks like at government scale. Your policy page asks for the same thing.

- Money changes who writes in. curl's confirmed rate fell from "somewhere north of 15%" before 2025 to "below 5%" in 2025, and in mid-2025 about 20% of submissions were what the lead maintainer, Daniel Stenberg, called AI slop. He ended the paid bounty at the end of January 2026 to "remove the incentive for people to submit crap and non-well researched reports". In the week before that announcement the program had seven submissions; some found bugs, none were vulnerabilities.

- It is not just AI. An academic study of Bugcrowd's public programs (January 2013 to June 2015) found 34.5% of submissions invalid. The noise came before the AI tools did.

- For you, the difference is time. curl is a high-profile project with a security team and still said the load was heavy. A five-person company has no triage queue.

A quick calculation for your own planning. Assume (ours, not measured) three junk reports a week, 20 minutes to check and reply to each, at a loaded cost of $75 an hour:

text
3 reports x 20 min        = 60 min a week
60 min x 52 weeks         = 52 hours a year
52 hours x $75            = $3,900 a year of attention

Real reports (assume 4 a year, 3 hours each to reproduce and fix):  12 hours = $900
Total                                                              ~ $4,800 a year

That is a cost to plan for, and it is why the canned replies matter. A rule that works: all reports go to a shared mailbox, one person owns Friday afternoon triage, and everything that is not clearly real gets one of the two replies above in under two minutes.

Paid bounty or yearly test?

A bug bounty pays per valid finding. A penetration test pays per week of one team's attention. For a small SaaS the question is what the money buys.

text
                          Yearly penetration test        Managed bug bounty (platform)
------------------------  -----------------------------  -----------------------------------------------
Typical 2026 cost         $5,000 (one app, tight scope)  Median contracts about $43,000 (HackerOne) to
                          to $15,000-$35,000 (multi-     $44,000 (Intigriti) a year per Vendr, before
                          role app with API)             any bounty payouts; list ranges are higher
Who looks                 One named team, one to two     Anyone invited, over months
                          weeks
What you get              A written report and retest    A trickle of reports, plus triage time
Fits when                 A customer or auditor asks     You have a product that changes weekly, a
                          for one                        security engineer and a hardened baseline
Risk                      Misses what the team did not   Noise, and duplicate findings you must pay
                          try                            for

The platform price figures are from aggregators (Vendr contracts as reported by CostBench in 2026); the platforms publish no price lists, and sources disagree widely (one gives $15,000 to $50,000 for smaller HackerOne programs, another $30,000 to $150,000 for Bugcrowd). HackerOne's own annual report puts payouts at about $81 million across all programs in the year to mid-2025, roughly $42,000 per active program, on top of fees. The test prices are the ones in our SOC 2 article.

Our own take, worked out with those numbers:

text
Year-one cost of a cheap yearly test                         $5,000 to $15,000
Year-one cost of a bounty (platform fee only, median)       ~$43,000
Plus payouts, e.g. 8 valid findings at $500 average         $4,000
Plus your triage time (as above)                            ~$4,800
Bounty total                                                ~$52,000

Bounty costs 3.5x to 10x a single test.

So the order for a small company is:

- First: the free page. security.txt and the policy above. Cost: an afternoon. It catches the honest strangers.

- Second: one test a year, with a retest included, scoped to the app that holds customer data. That is what questionnaires and cyber insurers ask for.

- Third: a small invite-only or self-run reward only after two clean tests, if you want to pay something. A fixed list of amounts on your thanks page works for some.

- A full public bounty when you have revenue that a breach would threaten, an engineer who can triage, and a security baseline you trust. Not before.

If you are not sure where your baseline is, the self-assessment below runs through the 25 Minimum Viable Secure Product controls and gives you a dated list of what is still open before anyone else looks.

Score your product against the 25 Minimum Viable Secure Product controls: yes, partly, not yet or not applicable, with a note and a date on each. Fix the gaps a stranger would find first, then publish your security.txt.

Open the security baseline self-assessment

Your afternoon checklist

- Create security@ as a shared mailbox read by at least two people (about 15 minutes).

- Write the one-page policy from the template above and put it at /security (45 minutes).

- Publish /.well-known/security.txt with Contact, Expires (about 11 months ahead), Policy, Preferred-Languages and Canonical (15 minutes).

- Run the curl checks above and confirm HTTP 200 and text/plain; charset=utf-8 (5 minutes).

- Save the two canned replies in your mail client (10 minutes).

- Add a calendar reminder 10 months ahead to renew Expires, and one to read the inbox every Friday.

- Add "security.txt and a disclosure policy: yes, reviewed 2026-11-14" to your questionnaire answers.

Total: about two hours of work. After that, the stranger who finds something knows where to go, and you have something honest to say when a customer asks.

Sources

RFC 9116: A File Format to Aid in Security Vulnerability Disclosure (April 2022) (fields, required and optional, location, content type, signing); URIports: Follow-Up on Security.txt Adoption (24 January 2025) (top one million domains, adoption and error rates); UK NCSC Vulnerability Disclosure Toolkit (communication, policy and security.txt); disclose.io (safe harbour definition and policy generator); US Department of Justice, revised CFAA charging policy (19 May 2022), as summarised by Morrison Foerster; Troy Hunt: Beg Bounties (8 November 2021); Sophos on beg bounty hunters; DC3: DoD Vulnerability Disclosure Program milestones and SecurityWeek on the 50,000th report (March 2024); CISA VDP Platform 2022 annual report summary; Daniel Stenberg: Death by a thousand slops (14 July 2025) and The end of the curl bug bounty (January 2026); The Register on curl ending its bounty (21 January 2026); Laszka et al., ESORICS 2016 (Bugcrowd invalid rate); Vendr on HackerOne and Intigriti and CostBench bug bounty pricing 2026 (contract medians and ranges). Cover photo: Pexels 277574 (Pexels License). The sample policy, the sample emails, the inbox-time arithmetic and the bounty-versus-test totals are our own.