Skip to main content
digital accessibility compliance for state and local government
Scan a site

Vulnerability disclosure policy

How to report something you have found, what we do with it, and how fast.

Last reviewed 27 October 2026.

In four lines

  • Send it to security@barrierops.com.
  • We acknowledge within 1 business day and either fix or explain.
  • We ask for 90 days before you publish.
  • There is no bounty. We say so rather than implying one.

What is in scope

BarrierOps has not yet taken on a customer, and no customer data has entered these systems. The scope below is what this policy covers rather than what is serving today — each row says which, so you can spend your evening on something that answers.

Every address, service and artifact this policy covers, and what each one is today. 8 rows.
In scopeWhat it is
barrierops.comThis marketing site, its tools, its published files and /.well-known/*
app.barrierops.comThe signed-in application. Deployed; it has no customers and holds no customer data.
api.barrierops.comThe API, including /api/v1/ and the internal endpoints. Deployed; it serves the signed-in application, the free scan, the GitHub App and the public API, v1, and has no customers.
*.barrierops.comEach customer’s public barrier-report portal and report status pages — specified, and not built: there is no portal to reach today
The BarrierOps GitHub AppIts permissions, its webhook handling and its check runs. Every permission it requests is published on our security page.
BarrierOpsBot/1.0Our crawler’s behaviour, its rate limiting, and anything it can be made to do
Our published artifactsThe 2028 checklist PDF and the OpenAPI document — including anything that can be smuggled through them. Our accessibility conformance report (VPAT) is not published yet and joins this row when it is.
Our emailAcknowledgement and digest templates, and anything injectable into them. The send path is not built, so there is nothing to inject into yet.

If you find something on a customer’s own website while testing us, tell us and stop. We will route it to that entity through the channel they already publish. Do not test it further and do not publish it — it is a public body’s website, not ours, and the person who pays for a mistake there is a resident.

What is out of scope

What this policy does not cover, and where each one goes instead. 6 rows.
Out of scopeWhere it goes instead
Our subprocessors’ own productsTheir own disclosure programmes. Tell us as well and we will chase it. The register on our security page is the list this row means.
A customer’s own website, CMS or vendor systemTell us; we route it. Do not test it.
Physical security, our offices, our postNot in scope, and not something we will act on
Social engineering of our staff, our customers or our subprocessorsNever in scope. Do not phone our support address pretending to be a customer.
Denial of service, load testing, resource exhaustionNever in scope, and it is the one thing that will end a conversation
Anything requiring access to another organisation’s data beyond proofStop at proof, and tell us — the rules of engagement below say what that means

The register the first row means is on our security page, with each provider’s region and what it can reach.

What is not a vulnerability to us

Published because it saves you an afternoon and saves us a reply. Each row says why, and none of them means we think less of the person who sent it.

Findings we will close, and the reason for each. 9 rows.
FindingWhy we will close it
A missing security header on a static asset with no origin stateWe set the headers that matter on the API and the app. A header on an immutable hashed asset changes nothing.
Self-XSS requiring the victim to paste into their own consoleIt is a browser feature and we cannot fix it
A rate limit on the public scan or the barrier formPublished, deliberate, and documented. Reporting the limit we publish is not a finding.
Software version disclosure without a demonstrated exploitWe publish our engine versions on purpose
Clickjacking on a page with no state to changeframe-ancestors 'none' is set everywhere including the public form. A framing report on a static article page is not a finding.
Missing SPF, DKIM or DMARC on a domain that sends no mailTell us anyway if it is a sending domain. On a parked one it is not a finding.
An automated scanner’s report with no reproductionWe will read it, and we will not triage it. One reproduced finding beats a 200-page PDF.
Absence of a bountyIt is stated in the summary and in security.txt. It is a decision, not an oversight.
Best-practice advice without a demonstrated impactSend it — we will thank you and we will not treat it as a report under this policy

What we commit to

Every window below is measured against 09:00–17:00 US Eastern, Monday to Friday, excluding US federal holidays — the same hours our security page and our about page state, from one constant.

What we commit to, numbered, each with the window it is measured in. 7 rows.
Commitment numberCommitmentWindow
1We acknowledge that a human has read your report1 business day
2We tell you whether we consider it a vulnerability, and at what severity5 business days
3We fix it, or we tell you in writing why we are not going toA target date, with the triage decision
4We keep you updated while it is open, without you having to askAt least every 10 business days
5We tell you when it is fixed, and how to verifyOn the day it ships
6We credit you by name if you want it, and never publish your identity without askingWith the advisory
7We publish an advisory when a fix affected customer data, and we tell affected customers directlyWithin 72 hours of becoming aware

If we miss one of these windows, tell us, and if we still do not answer, publish. We would rather be embarrassed by a researcher than run a policy nobody can hold us to.

Outside the stated hours nothing acknowledges your message automatically — we have not built that yet, and saying otherwise would break the first window on this page before anybody read it. A report sent overnight is read in the morning. The one engineer on call outside hours is paged for outages and failed integrity checks of the evidence ledger, not for disclosure triage, and pretending otherwise would be a commitment we cannot keep.

What we ask of you

A good report is mostly a form somebody filled in without being given one. This is the form, and there is nothing to submit it through on purpose.

What to put in a report, and why each one helps. 9 rows.
AskWhy
What you found, in one sentenceIt routes the report
Where — the exact URL, endpoint, header or fileA finding we cannot locate is a finding we cannot reproduce
How to reproduce it, step by stepThe single thing that decides whether this gets fixed this week or next quarter
What an attacker getsImpact, in your own assessment. We will disagree politely if we do.
The account or API key you used, and its prefixSo we can find your requests. bo_test_ keys are preferred.
Timestamps in UTC, and your source IP addressesSo we can correlate against our logs
Whether you used automated tooling, and at what rateSo we do not investigate you as an incident
How you want to be credited, or that you do notWe ask rather than assume, and we never publish a name without being told to
Whether you have told anyone elseNot a trap. It changes our timeline, not our attitude.

We do not publish a PGP key yet, so there is no encrypted channel to offer and we are not going to link one that does not resolve. Plain email is fine and most reports arrive that way. If a finding is too sensitive to send in the clear, say so in an empty message and we will arrange a channel before you send anything.

We do not require an NDA, an account, a legal agreement or a form. An email is a report.

Rules of engagement

  • Test against the sandbox where you can. Test mode is keyed by bo_test_ and is backed by a seeded fixture organisation. It is realistic enough to find real bugs in and it touches no customer data: a bo_test_ key reads only the sandbox’s fictional organisations, City of Riverbend among them, and changes nothing. The API documentation says how to create one.
  • Never access another organisation’s data beyond what proves the finding. One record id is proof; a dump is not. We will not treat a stop-at-proof as an intrusion. We will treat a dump as one.
  • Do not modify or delete anything that is not yours, and do not create load that affects another customer.
  • No denial of service, no brute forcing at volume, no automated scanning above 10 requests per second. Tell us your source addresses and we will allow them.
  • No social engineering, no phishing, no physical access, and nothing involving our staff or our customers’ staff as targets.
  • Do not use a finding to pivot into a customer’s own systems. The customer is a public entity and the blast radius is a city.

Safe harbour

We will not pursue or support legal action against you for security research conducted in good faith under this policy. That means: you followed the rules of engagement, you stopped at proof, you did not access, modify or retain data beyond what the finding required, and you gave us a reasonable chance to fix it before publishing.

If you are unsure whether something is in bounds, ask first at security@barrierops.com and we will answer. Asking has never once made a report worse.

This is a statement of our intent, not a licence to break a law we do not control. We cannot waive a third party’s rights, and we cannot promise what a subprocessor or a customer will do — which is why the scope section asks you to stop rather than continue when you find yourself on somebody else’s property.

There is no bounty

There is no bounty, no swag, and no payment of any kind. This is a small company, and a promise of money we could not fund reliably is one we would eventually break — which is exactly the failure mode this whole page is built to avoid.

What you get instead: an answer from a person, a fix with a date, a published advisory, and credit by name if you want it.

If a paid programme ever exists, it will be announced here, it will not be retroactive, and we will say that too.

The machine-readable version

The contents of /.well-known/security.txt

# BarrierOps — digital accessibility compliance for state and local government
# Policy: https://barrierops.com/security/disclosure

Contact: mailto:security@barrierops.com
Contact: https://barrierops.com/security/disclosure
Expires: 2027-10-27T00:00:00.000Z
Acknowledgments: https://barrierops.com/security/disclosure#acknowledgements
Preferred-Languages: en, ro
Canonical: https://barrierops.com/.well-known/security.txt
Policy: https://barrierops.com/security/disclosure

Served as text/plain over HTTPS at the canonical path, per RFC 9116. Expires is generated from the last review date, never typed — the build fails rather than serving an expired file.

Preferred-Languages lists the languages a person here can actually read a report in. Listing a language nobody reads is a way of losing a report, so it is two rather than three: our Spanish privacy notice has not been read by a native speaker yet, and until it has, offering Spanish here would be offering a slower answer.

The live file is at /.well-known/security.txt, and it is the same bytes as the block above — the page reads the file rather than keeping a second copy of it.

Acknowledgements

No reports have been received under this policy yet. This list is not empty because anything was removed from it. When it stops being empty it will be dated.

Where else to write

Where to write about something this policy does not cover. 4 rows.
SubjectWhere
A security findingsecurity@barrierops.com — This policy
Our crawler, including how to slow it down or block it/bot — Which also reaches a person
Privacy, a resident’s data, a deletion request/privacy — Which names the public entity to ask, and why it is them rather than us
Anything else/contact

Our crawler sends BarrierOpsBot/1.0 (+https://barrierops.com/bot), and the address inside that string is our crawler page. It is where a municipal administrator lands first after finding us in a log, which is why it is named here as well as in the table: a security finding should not end up filed as a crawler complaint.

https://barrierops.com/security/disclosure