Skip to content

feat(agent): local Web Bot Auth verification in detectBot() (#323) - #10

Merged
cport1 merged 1 commit into
mainfrom
feat/323-web-bot-auth-sdk
Jul 24, 2026
Merged

cport1 merged 1 commit into
mainfrom
feat/323-web-bot-auth-sdk

Conversation

@cport1

@cport1 cport1 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Implements WebDecoy/app#323 — local Web Bot Auth verification in the Node SDK. Part of the Agent Identity & Trust Layer milestone (app#331); the SDK half of Phase 2 FR5, and it upgrades the Vercel bot-detection story (app#284/#299) from parity to lead.

Supersedes PR #9 (auto-closed when its stacked base feat/281-edge-runtime-compat was merged+deleted via #8). Same branch, now retargeted at main; #281 is already merged so this diff is only the #323 changes.

What it does

AI agents (OpenAI Operator, ChatGPT, the IETF webbotauth cohort) cryptographically sign their requests (RFC 9421, tag web-bot-auth). This verifies those signatures in-process, on Node and every WinterCG edge runtime — no API key, zero network on the warm path.

Two entry points:

  • wd.detectBot(request) — returns a verdict; the developer decides. Accepts a WHATWG Request (edge/Next.js) or { method, url, headers } (Node).
  • webBotAuth() rule — drops into the rules engine and denies impersonation of known agents by default. The verdict is precomputed async into RuleContext.agent (the same pattern filter rules use for IP enrichment), so the sync rule can act on it. Also surfaced on ProtectResult.agent.

Verdict taxonomy (matches ingest app#320 + the edge validator)

status meaning default action
verified signature validated against a trusted agent key (name + category populated) allow
impersonation claimed a known agent's key but failed crypto/window — a forgery deny
claimed signature present but unverifiable (unknown/malformed signer) let other rules decide
none no signature continue

Design

  • New agent/ module, zero deps: RFC 8941 SFV parser, RFC 9421 signature base, JWK-thumbprint keyids (RFC 7638/8037), WebCrypto Ed25519 + RSA-PSS-SHA512.
  • Curated directory client — only fetches an allowlist of trusted agent directories (default: OpenAI, tracking backend signed_agents.go); a request's own Signature-Agent header never selects a fetch target, so there's no SSRF surface. Stale-while-revalidate cache keeps verification off the network once warm.

Acceptance criteria

  • Signed request verified locally — warm-path p95 < 5ms (test asserts it)
  • Impersonation verdict deny-able in middleware — webBotAuth() rule, onImpersonation: 'DENY' default
  • Works on Vercel Edge runtime + Node — full verification runs inside a real @edge-runtime/vm; check:edge passes
  • Doc page — docs/verify-ai-agents-web-bot-auth.md ("Verify AI agents with Web Bot Auth in Next.js")

Tests

packages/webdecoy/src/agent/web-bot-auth.test.ts (signatures built by hand from the RFC base, so a base-construction bug fails verification rather than passing): verified, tamper→impersonation, expiry→impersonation, unknown-key→claimed, host-unbound→claimed, none, Node {method,url,headers} path, warm p95<5ms, RFC 7638 thumbprint KAT. Plus the webBotAuth rule unit tests and the Edge-VM case. Full suite: 129 passing, all packages build, both @webdecoy/node and @webdecoy/nextjs edge-compatible.

…/app#323)

Verify inbound AI-agent signatures (RFC 9421 HTTP Message Signatures, tag
"web-bot-auth") locally in middleware — on Node and every WinterCG edge
runtime — with no API key and zero network on the warm path.

- New agent/ module: a zero-dep RFC 8941 SFV parser, RFC 9421 signature-base
  construction, JWK-thumbprint keyids (RFC 7638/8037), and a cached, curated
  directory client (Ed25519 + RSA-PSS-SHA512 via WebCrypto). Curated-only, so
  a request's Signature-Agent header never selects a fetch target (no SSRF);
  stale-while-revalidate keeps the warm path off the network.
- WebDecoy.detectBot(request) — returns a verdict (verified / impersonation /
  claimed / none) with agent name+category for verified agents. Accepts a
  WHATWG Request or { method, url, headers }.
- webBotAuth() rule — denies impersonation of known agents by default; the
  verdict is precomputed async into RuleContext.agent (same pattern as filter
  rules + IP enrichment) so the sync rule can act on it. Surfaced on
  ProtectResult.agent.
- Verdict taxonomy matches the ingest verifier (WebDecoy/app#320) and the edge
  validator; curated directory list tracks backend signed_agents.go.

Tests: signed→verified, tamper/expiry→impersonation, unknown-key/host-unbound
→claimed, none; warm-path p95 < 5ms; RFC 7638 thumbprint KAT; and full
verification running inside a real Vercel Edge Runtime VM.
@cport1
cport1 merged commit bcf4be9 into main Jul 24, 2026
@cport1
cport1 deleted the feat/323-web-bot-auth-sdk branch July 24, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant