2026-07-15

AI Agent Traffic Authentication: A 32-Case WBA Gate

A failure-first Web Bot Auth drill shows why an AWS WAF verified label must still pass origin route, rate, replay, content, and application-authorization gates.

AI Agent Traffic Authentication: A 32-Case WBA Gate cover illustration

Failure-first WBA policy drill

A green Web Bot Auth label is not an authorization decision. It says AWS WAF validated a signed automated request against a known public key. It does not say the bot may use this hostname, route, method, account, rate, or application action.

That distinction is easy to lose because the current Bot Control documentation says a web_bot_auth:verified request no longer matches CategoryAI and TGT_TokenAbsent. The request can pass those managed-rule checks and still deserve a rejection at the next boundary.

We translated the boundary into a 32-case local admission ledger. One signed read and one separately authenticated write passed. One signed write stopped for application step-up. The other 29 packets failed on identity, coverage, freshness, replay, route, rate, or WAF-order controls.

Retained result: all 32 expected decisions matched. The fixture produced 1 scoped read, 1 scoped write, 1 step-up, and 29 blocks across 19 distinct reasons. Fixture SHA-256: 587688811d18e4106f0f524f38504eb83662af397fd08c334154f2e2e7860c06.

The signature ends one argument and starts another

IP ranges and user-agent strings are weak identity evidence for multi-tenant agent platforms. A copied header is free. A shared egress address can represent thousands of unrelated workloads. Web Bot Auth addresses that problem by binding selected HTTP components to an asymmetric key and publishing the matching public key through a signature directory.

A successful verification settles a narrow question: did the holder of this key sign the covered request components inside the accepted time window? The origin still owns the consequential questions. Is this exact bot identity registered? May it read this collection? Can it mutate a ticket? Is the request volume plausible? Has the nonce already been consumed?

Authentication narrows the principal. Policy narrows the action.

32synthetic packets in the retained admission fixture
2complete paths allowed after every required control
1validly signed write paused for application authentication
29mutations rejected before an origin-side operation

These counts describe our deterministic policy fixture, not AWS WAF conformance coverage and not a live service test.

Validation ledger: what AWS puts on the wire boundary

The current AWS Bot Control rule-group documentation lists four Web Bot Auth outcomes under the awswaf:managed:aws:bot-control:bot: namespace. The same request can also carry bot name, category, organization, vendor, and—for Amazon Bedrock AgentCore—an opaque account label. Those fields are useful precisely because a bare “verified” result is too broad for origin policy.

WBA resultWhat it establishesWhat it does not establishOur first action
verifiedThe signature validated against the public-key directory.Route permission, application scope, safe rate, benign intent, or replay safety.Continue to identity and route policy.
invalidSignature material was present but cryptographic validation failed.Whether the failure was an attack, corruption, or bad rollout.Block and preserve a bounded diagnostic sample.
expiredThe signature used expired cryptographic key material.Whether a rotation cache or retired signer caused the event.Block and page the key owner.
unknown_botThe key identifier was absent from the verifier's directory view.Whether registration is pending or the identity is fabricated.Block protected routes; measure public-route demand separately.
Blueprint-style cutaway of four signed request capsules separated into distinct verification lanes, with the intact lane facing another locked gate
The verifier sorts identity evidence. The origin still decides whether the intact capsule belongs on this route.

Rule order matters. Bot Control must evaluate before a label-matching rule can consume its output. A static managed-rule version also belongs in the deployment record; quietly floating the version changes the verifier while the origin policy appears untouched. The managed group currently consumes 50 WCU, so capacity and cost belong in the change review too.

A passing packet carries more than a green label

Our allowed read targets GET /knowledge/runbooks on one hostname. The synthetic request uses TLS, covers authority, method, path, and the signature-directory reference, stays inside a two-minute freshness window, presents an unseen nonce, matches the registered vendor/account/name tuple, stays under 30 requests per minute, and has no managed threat signal.

Remove any one of those controls and the decision changes. That may look strict for a read path. It is also reviewable: every acceptance fact is visible in one ledger row rather than implied by a generous WAF allow rule.

Verifier railManaged group, pinned version, rule order, WBA outcome, bot labels, and threat signals.
Signature railCovered authority, method, path, directory reference, creation time, expiry, and nonce.
Origin railHostname, registered identity tuple, path prefix, HTTP method, and route-specific rate.
Application railContent digest, intent identifier, application token, idempotency, and business permission.

Keep those rails separate in telemetry. A single “agent allowed” counter cannot tell whether signatures are failing, registration drifted, rate policy is too tight, or the application rejected a perfectly authenticated writer.

Coverage is the quiet security boundary

RFC 9421 lets an application sign selected HTTP fields and derived components. Selection is powerful and dangerous. A valid signature over the wrong set of components can authenticate bytes that do not constrain the action the server eventually performs.

The Web Bot Auth architecture draft requires at least @authority or @target-uri. Our admission policy goes further for protected routes: it also requires @method, @path, and the directory reference. A write additionally requires a covered content digest. Without those bindings, an intermediary or replay path can preserve a valid signature while moving the request to a different operation.

TLS remains mandatory. HTTP Message Signatures add authenticity and integrity for covered components; they do not encrypt the payload, and RFC 9421 explicitly treats confidentiality as a separate property.

Failure modes: replay changes with consequence

A repeated crawl of a public document and a repeated refund are not equivalent failures. Both can carry valid signature bytes. Only the application knows whether duplication is harmless, idempotent, expensive, or irreversible.

The local ledger rejects missing and previously seen nonces. It also caps both signature age and forward expiry at 120 seconds. Those numbers are a policy choice for this fixture, not an AWS default. A real cache must define its scope, eviction behavior, clock-skew tolerance, and outage posture before enforcement.

Blueprint-style nonce wheel blocking a duplicate request capsule while a content seal and separate application key align for one write path
A signature can be valid twice. The nonce store, content binding, and application intent decide whether the second arrival is safe.

Do not put a global replay cache in front of every route without modeling its memory and failure mode. A low-risk read may accept bounded duplication during cache degradation. A mutation should instead use an application idempotency key whose result can be replayed safely, or fail closed if that store is unavailable.

Why the signed write stopped

One fixture packet had a valid WBA identity, correct host and route, covered method/path/content digest, fresh timestamps, and an unseen nonce. It still returned REQUIRE_APPLICATION_AUTH. The missing facts were an application token and an intent identifier bound to the business action.

This is deliberate. Bot identity describes the automation operator. Application authorization describes the user, tenant, delegated scope, approval state, and object being changed. Collapsing the two creates a universal credential: compromise one browser signer and every origin action gated only by “verified” becomes available.

The fully accepted write adds the narrow application facts and stays under a four-per-minute write limit. Its WBA signature is necessary but insufficient. That is the policy shape worth preserving.

Rotation has two clocks, not one

A bot operator publishes public keys; AWS WAF polls directories and maintains a registry. The operator therefore controls signer rotation while the verifier controls refresh timing. The origin sees the consequences as verified, expired, or unknown_bot labels.

A rotation drill should observe all three systems. Introduce the new key, wait for verifier recognition, canary signed reads, move traffic, retire the old key, and prove the retired key no longer reaches the origin policy. Record directory publication time, first verified observation, last old-key observation, and the rollback owner. “New key exists” is not a completion criterion.

Keep the signing key outside prompts and model-visible logs. AgentCore Browser can sign automatically when WBA is explicitly enabled at browser creation, but AWS still describes the feature as preview and based on an evolving IETF draft. Pin assumptions to a test date rather than promising a permanent header shape.

The rollout has three reversible cuts

First, observe. Add Bot Control, pin the selected static version, preserve ordinary managed protections, and count each WBA outcome by host, path, bot identity, and action. Do not create a broad verified-bot allow rule.

Second, constrain reads. Register exact vendor/account/name tuples and open one low-consequence path with a route-specific rate. Run unsigned, invalid, expired, unknown, stale, replayed, cross-host, cross-path, and excessive-rate cases. Each should land in the expected bucket.

Third, step up writes. Cover method, path, and content digest; bind an application identity and intent; add idempotency; use a tighter rate; and rehearse loss of the nonce or idempotency store. Expand only after the negative cases are as observable as the happy path.

Decision: use WBA to replace spoofable bot identity hints, then keep authorization at the origin. A verified label may bypass two AWS bot-classification rules; it must not bypass your route, rate, replay, or application controls.

Pinned records behind the decision

The retained harness is deterministic JavaScript over synthetic packets. It did not access an AWS account, create a WAF web ACL, start AgentCore Browser, sign a real request, fetch a public-key directory, touch a protected origin, read credentials, or alter production traffic.