v1.15.0 - Web Bot Auth Signature Verification
Upgrades Web Bot Auth (RFC 9421 HTTP Message Signatures) handling from a presence-only header check to real cryptographic verification against the signer's published key directory. A presence check can't tell a genuine signer (OpenAI Operator, etc.) from three spoofed headers; verification can.
Verdict model
Identical across Go and Node:
- verified →
declared_ai(verified:true, high confidence): a trustworthy signed identity. A policy signal, not a hard block. - forged →
bot(low confidence, contributory): the signature failed cryptographic verification — affirmative evidence of a spoofed identity claim. Only a genuine crypto failure counts. - otherwise → fail open to a presence-only signal, identical to the previous behavior. An unreachable or blocked directory is not proof of spoofing, so it never accuses.
False-positive guardrail
Only a cryptographic verification failure scores as forged. Every ambiguous outcome — unreachable/blocked directory, timeout, expired signature, key-not-found — fails open to the presence-only signal. Verification also runs in the HTTP handler using the real request, so the signature base (@authority/path/scheme) is reconstructed accurately; a lossy header-map approximation could fail a legitimate signature and false-positive a real agent. Verdicts feed scoring via a new preDetections path so they actually affect the score.
Scope
- Go (
server-go/): usesgithub.com/WebDecoy/web-bot-auth— zero-dependency, SSRF-guarded directory client built in. Requires Go 1.23 (go.mod+ Dockerfile bumped). - Node (
server-node/): builds an SSRF-guarded directory fetch (ipaddr.js: public-unicast only — blocks loopback/private/link-local incl. the cloud metadata IP; https-only; no redirects; size-capped; cached) around Cloudflare'sweb-bot-authcrypto primitives, the reference implementation the Go module is cross-validated against. - Python (
server-python/): unchanged (presence-only) — no maintained library exists; documented gap.
Covered by Go tests (real-Ed25519 end-to-end verified/forged, verdict mapping, scoring participation) and framework-free Node tests (npm run test:webbotauth: SSRF guard, header parsing, verified/forged/fail-open).
Caveat: in a real embed the signature is over the agent's page request, not the /verify XHR — verification only fires if those signature headers reach the scoring endpoint. The directory fetch is the first networked step in the scoring path (cached, short timeout, fail-open). Implements PRD phase 6.
Full changelog: v1.14.0...v1.15.0