Last updated 11 September 2026
Security
What protects your account, your reports and this website, and how to tell us about a vulnerability. Every measure listed here is one the code implements today. Where a protection has a limit, the limit is stated.
1. Your account
Sign-in is handled by Supabase Auth, and passwords are stored only in hashed form. When you set a password, it is checked against known breaches using the Have I Been Pwned range API. Only the first five characters of the password's SHA-1 hash leave your browser, so the password itself is never sent to that service.
Two-factor authentication is optional. You can turn it on from your account page with any authenticator app that supports time-based one-time codes (TOTP).
2. Your reports
A report is private to the account that ran the scan. Anyone else, signed in or not, gets the same answer as for a report that does not exist.
Sharing is opt-in. A share link carries a random secret of its own and opens that one report, nothing else in your account. A link works for 30 days; you can renew it, which keeps the same address, withdraw it at any time, or replace it, which cancels the old one. Scans started by the Accessibility Pro GitHub Action are the exception: they are created with a share link already attached, because the Action posts the report link into your pull request for readers who have no account. That link expires after 30 days like any other, and the Action can be told to make none.
When a report is opened through its link, the time is recorded and shown to the report's owner as a count and the date of the last open. Opens in the same minute count once. That record holds nothing about the reader: no address and no browser details.
An account can switch share links off altogether, under Account. No link then opens any of its reports, none can be made, and its GitHub Action scans get no report link.
3. Where data is kept
The database is hosted by Supabase in the EU (region eu-north-1). Row-level security is enabled on every table, and the browser reaches the database only through those policies. The scanning backend uses the service-role key, which is held on the server and never sent to the browser.
Card payments are handled by Stripe. Card numbers never reach us; we store your Stripe customer identifier and your plan. What personal data is kept, and for how long, is set out in the Privacy Policy
4. This website
Every page is served with a Content Security Policy that attaches a per-request nonce (or a hash) to each inline script and forbids framing. Responses also carry Strict-Transport-Security, X-Frame-Options DENY, X-Content-Type-Options nosniff, a strict-origin-when-cross-origin referrer policy, and a Permissions Policy that turns off camera, microphone and geolocation.
5. Scanning and patches
The scanner refuses targets that resolve to private or internal network addresses. Suggested code fixes are tested in a sandbox against the captured copy of the page, never against your live site. How to recognise the scanner in your logs, and what to allow if your firewall refuses it, is on the page about allowing the scanner
6. Reporting a vulnerability
Email us, with “Security” in the subject line, at support@accessibilitypro.app Include the affected URL or endpoint, the steps to reproduce, and what an attacker could do with it.
While testing, please use only your own account and your own data. Do not access, change or delete anyone else's data, and do not run tests that slow down or interrupt the service for other people. No bug bounty is offered.
The same contact details are published in machine-readable form at /.well-known/security.txt