wbactl
Static/CI toolkit for Web Bot Auth — the IETF profile of RFC 9421 that lets agents and bots sign their HTTP requests (draft-ietf-webbotauth-httpsig-protocol-00).
Four jobs, all local-first, no server, no telemetry:
check— agent-side doctor: why is my agent blocked? Compares unsigned vs signed request outcomes and validates your key directory setup.conformance— verifier test vectors: run the bundled accept/reject vectors against a verifier implementation (bundled reference verifier, an HTTP service, or a command).audit— passive adoption audit of public AI-access signals: robots.txt AI rules, AIPREFContent-Usage,Content-Signal, and WBA key directories.keygen/directory— generate an Ed25519 signing key and the JWKS directory document to host at the well-known path.
Status: early work in progress (pre-1.0).
Dataset: State of Agent Access — 2026-09.
Install
pip install wbactl
Development:
uv sync --all-groups
uv run wbactl --help
Quickstart
# 1. Generate a signing key and the JWKS directory document
uv run wbactl keygen --out ./wba
# 2. Host ./wba/wba-directory.json at
# https://your-domain.example/.well-known/http-message-signatures-directory
# 3. Diagnose a URL as an agent
uv run wbactl check \
--url https://example.com/some/page \
--key ./wba/wba-private.pem \
--signature-agent https://your-domain.example
# 4. Run conformance vectors against a verifier
uv run wbactl conformance # bundled reference verifier
uv run wbactl conformance --target-url http://localhost:8080/verify
uv run wbactl conformance --target-cmd "my-verifier --stdin"
# 5. Passively audit public AI-access signals
uv run wbactl audit --domains domains.txt --out audit-raw.jsonl --delay 1
Conformance target contract
--target-url receives a POST with
{"method","url","headers","now","keys"} and must return
{"accepted": true|false, "reason": "..."}. --target-cmd gets the same JSON
on stdin and must print the same JSON on stdout (a non-zero exit is fine when a
verdict was printed).
The target MUST treat now as the current time and apply any max-age policy
against it; vectors use fixed timestamps and are otherwise unverifiable.
Audit ethics
audit fetches only public metadata (robots.txt, response headers, the
well-known key directory) with a fixed delay and an honest User-Agent. It never
probes like an agent, never executes anything, and does not follow more than
three redirects. Never publish the raw JSONL: publish aggregates and
hand-validated examples of public metadata only.
Spec revision
The supported draft revision is pinned in src/wbactl/spec.py
(draft-ietf-webbotauth-httpsig-protocol-00, 2026-09-01). Bump it deliberately
and update fixtures when the draft changes.
Interop
- Known-answer tests against
cloudflare/web-bot-authreference output: legacy and structured signatures reproduce byte-for-byte (tests/test_sign.py). - Cloudflare architecture vectors (vendored, Ed25519) verified in
tests/test_cloudflare_vectors.py. - Manual smoke (2026-09-25): legacy
wbactl-signed requests are accepted by Cloudflare's live test deployment. - Known upstream inconsistency (observed 2026-09-25, not yet confirmed
upstream): that deployment rejects the RFC 9421 §2.1.2 Dictionary
member-value structured signature that
cloudflare/web-bot-authitself produces; wbactl follows the RFC and the reference library.
License
Apache-2.0
Metadata
Release files for wbactl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wbactl-0.1.0.tar.gz | 70.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wbactl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.1 kB
Release files / wbactl-0.1.0.tar.gz
| Download URL | wbactl-0.1.0.tar.gz |
|---|---|
| Size | 70.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54de717db74c031762eb0dcc99ecd4fc05c69211ba4e74f76e2d6d571290e624
|
|
BLAKE2b-256 checksum How to use checksums |
4c03b9c194a921be9bff76dc011a7ee2b0b751ae557ce58d6f91dfd3029740ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / wbactl-0.1.0-py3-none-any.whl
| Download URL | wbactl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 32.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d025821d8c97a93ee3d3d9d1ba616054c4823dc6a0dadfe97281fc9d65f6d9e9
|
|
BLAKE2b-256 checksum How to use checksums |
b907906b879b91286a13e54d49264800c8e1fc25a5ad43448c0af304a30d4921
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|