v1.30.0
Fixes a token verification bug that rejected legitimate traffic in any deployment where the backend and the visitor are different hosts — which is most of them.
Fixed
Token verification compared the wrong two addresses.
POST /api/token/verify checked the token against the socket address of whoever called the endpoint. But a token is minted for a browser visitor, while the verification call comes from your backend. Those are the same host only on a developer's laptop. Everywhere else, the check compared a visitor's address against a server's and rejected a perfectly good token.
The endpoint now follows Siteverify semantics:
remoteipsupplied — the token is checked against that address, which should be the visitor IP from the original browser request. A mismatch returnsip_mismatch.remoteipomitted — no IP check is performed.
The verification caller's own socket address is never used for this comparison.
{
"token": "...",
"secret": "your-secret",
"remoteip": "203.0.113.10"
}Fixed in Go, Node and Python. If you worked around this by co-locating verification with the visitor-facing edge, you can stop. If you want IP binding, pass remoteip explicitly — it is now opt-in rather than implicit and wrong.
Added
A cross-server conformance suite. test/conformance.js runs one shared contract against each server's production container in CI, so a security invariant cannot hold in one implementation and quietly not in another.
It deliberately does not compare detector scores — those differences between the three servers are known and documented. It pins the places where a difference is a security or integration defect:
- proof of work is required
- tokens and challenges are single-use
- signal commitments cannot be swapped
- verification authentication and optional visitor-IP binding
- signed hostname, action and cdata claims
- Siteverify form encoding, shape and idempotency
- request-size and HEAD behaviour
Documented in test/CONFORMANCE.md, and runnable locally against any of the three servers.