Security
Last updated 23 August 2026
How the service is built, what it stops, what it does not, and why we do not have a SOC 2 report.
The one property that matters
The answer to a challenge never reaches the browser. It is generated on our server, held there for at most two minutes, and compared there exactly once. There is no code path that sends it to a client, so no amount of DOM inspection, memory reading, or breakpoint setting recovers it. Most client-side widgets cannot say this; it is the difference between a challenge and a decoration.
Controls
| Control | Detail |
|---|---|
| Answer isolation | Generated, stored and graded server-side. Never serialized into any response. |
| Attempt limit | Four guesses per challenge against a 1-in-100 space, then the challenge is destroyed. A 4% ceiling on blind guessing. |
| Single-use tokens | Redemption deletes the token. A valid signature is not sufficient; replay inside the TTL fails. |
| Token binding | HMAC-SHA-256, bound to one site key. A token minted for one site will not verify against another site’s secret. |
| Short lifetimes | Challenges expire in 2 minutes, tokens in 5. |
| Origin allowlist | Challenges are refused for origins outside your configured domains. |
| Rate limiting | Token bucket on issuance, grading, provisioning and verification, keyed on a salted hash rather than an address. |
| Constant-time comparison | Secrets are compared in constant time, and “no such key” is indistinguishable from “wrong secret”, so the API cannot be used to enumerate keys. |
| Transport | TLS 1.2 minimum, HSTS. |
| Dependencies | The server has none. Nothing from npm runs in the request path, so the service has no exposure to a compromised transitive package. |
What we do not stop
We publish this in full rather than leaving you to discover it. The threat model carries the measurements; the summary:
- A solver written specifically against us. Matching dots between consecutive frames recovers the glyph at a correlation of 0.84 against ground truth — legible enough to read by eye. We tried several configurations to close this and could not. The reason is structural: the human visual system recovers the shape by solving the same correspondence problem, so anything that defeats the algorithm defeats the person by the same amount. Rendering server-side video instead does not help — optical flow recovers it too, for three to six times the bandwidth.
- Human solving farms. A person paid to solve these solves them. The mechanism is built for human legibility, so this is definitional, and it is true of every CAPTCHA on the market.
- Relay to an unwitting third party. Token TTL and single use bound the window; they do not close it.
What the product does stop is a general-purpose model looking at the screen — the autonomous browser agents, scripted signup floods and commodity scrapers that make up the traffic people actually buy a CAPTCHA for. If a funded attacker is targeting you specifically, no CAPTCHA is your answer; rate limiting, identity proof, and payment friction are.
Accessibility
The challenge is visual and depends on motion, and there is currently no non-visual alternative. People who are blind or have low vision cannot solve it. Nor, in general, can people with a vestibular disorder or motion sensitivity, since motion is the mechanism rather than decoration.
We are not going to dress this up. If you are subject to the European Accessibility Act, the ADA, WCAG 2.2, or an equivalent obligation, do not make this the only route to your form. Keep an alternative path open — a phone number, an email address, or a staffed channel — and say so next to the widget.
An accessible alternative is the single largest gap in the product and we are working on it. We would rather say that than ship a page claiming otherwise.
Data handling
The service holds no personal data about the people who solve challenges: no cookie, no device storage, no fingerprint, no retained IP address, no behavioral signals. Rate limiting hashes the address under a salt that lives in memory, is never written down, and is destroyed on restart. Full detail in the privacy policy.
Why there is no SOC 2 report
Because there is nothing in scope for one to cover.
A SOC 2 Type II report is an auditor’s opinion on whether an organisation’s controls over customer data operated effectively over a period. It is the right question to ask a vendor that holds your users’ records — a CRM, a support desk, an analytics platform, a payment processor. The report is valuable exactly in proportion to how much of your data the vendor is holding.
We hold none of it. Not a reduced amount, not an anonymized amount — none. A challenge request arrives, a challenge goes back, an answer arrives, a token goes back, and within five minutes every record involved has been deleted. There is no user table. There is no event stream. There is no data warehouse. A Type II audit of that surface would examine an empty room and produce a certificate attesting that the room was, over a twelve-month observation period, empty.
What we do hold is your account: a label, a domain list, an email address, and a daily counter. That is worth protecting, and the controls above are how we protect it — but it is not the thing a SOC 2 request is usually trying to get comfortable about.
What we offer instead
- Read the source. The server is a few hundred lines with no dependencies. You can read every line that touches a request in an afternoon — a stronger assurance than an opinion letter about code you cannot see.
- The published threat model, including attacks we have measured working against us. We would rather hand you the failures than have you find them.
- A completed security questionnaire — SIG Lite, CAIQ, or your own form. Email security@blockagents.ai.
- Self-hosting. The strongest answer to a vendor risk question is removing the vendor. Run it in your own VPC and no request leaves your infrastructure, which makes our control environment irrelevant to your assessment.
- Penetration test on request for annual contracts.
We will say plainly that this argument does not always win. Some procurement processes require a report regardless of scope, and if yours is one of them we would rather tell you now than six weeks into a review. If enough customers need it, we will get one; we would just rather spend that money on the accessibility gap above, which is a real problem rather than a paperwork one.
Reporting a vulnerability
security@blockagents.ai. We confirm receipt within two business days. Test only against your own site keys, do not degrade the service for others, do not access data that is not yours, and give us 90 days before publishing. We will not pursue legal action over research on those terms.