Skip to content

Session Clearance

Session clearance is WebDecoy’s enforcement gate for browser traffic. Instead of blocklisting fingerprints and IP addresses (which either miss rotating bots or catch innocent users), protected routes require a signed clearance token, carried in the wd_clearance cookie. Real browsers earn one automatically. A client that trips a decoy or SDK tripwire is denied clearance on every IP it rotates to, and its current token is revoked within about a minute.

  • An edge validator in front of your site: a Cloudflare Worker, an AWS Lambda@Edge function on CloudFront, or the WebDecoy Netlify extension with its gate turned on (see Clearance Enforcement)
  • The SDK script tag installed with your site key, so real browsers earn tokens in the background as they browse
  • Enforcement mode set to Enforce (Monitor is the default)
  • At least one token-enforced route scoped. With no routes scoped, the gate stays off even in Enforce mode
  1. Mint in the background: the SDK script tag silently mints the wd_clearance cookie while a visitor browses their first pages; no interstitial, nothing to click. With browser client 0.18.5 or later, fresh cookies are reused and renewal continues before expiry throughout a long session. A visitor who deep-links straight to an enforced HTML route before the cookie exists gets an invisible check that mints it and reloads. API requests receive a JSON 403; the browser client offers an explicit helper for one safe-read retry, and never replays mutations. See Browser Client for renewal, retry and refusal behavior.
  2. Verify at the edge: subsequent requests carry the cookie, and the edge validates it with no round-trip to your origin.
  3. Deception revokes: a decoy or SDK tripwire hit that carries the cookie automatically puts that client’s token fingerprint on the deny-list: it cannot mint a new token from any IP, and its live token stops validating within about a minute. Denials last 30 days by default and can be revoked manually at any time. By design, only deception signals feed the deny-list. Heuristic rules like rate limits and filters never do.
Client What happens on an enforced route
Real browser Passes the check once, carries clearance, never sees it again
Verified crawler (e.g. Googlebot) Passes via the verified-crawler allowlist, never challenged
Your own machine clients Pass via a machine service token
Bot that trips a decoy or tripwire Deny-listed: current token revoked, re-minting refused, on every IP

Updated Cloudflare and Netlify validators, and Lambda’s supported refusal paths, return HTTP 403 with Cache-Control: no-store and the existing x-wd-clearance: challenged header. API responses also include:

x-wd-challenge: 1
x-wd-challenge-reason: missing
x-wd-challenge-recoverable: true
{
"error": "clearance required",
"challenge": { "version": 1, "reason": "missing", "recoverable": true }
}
Reason Recovery through the application’s verification flow
missing, invalid (including expired clearance) May earn replacement clearance
insufficient-trust Must earn the route’s stronger grade
revoked, crawler-refused, agent-impersonation, denied No automatic recovery

Unknown refusal reasons become denied with recovery disabled. The recoverable bit is a client hint, never authorization. All decisions, revocation, minimum grades and outage behavior remain server-owned. Lambda reports its own actual verdicts; this contract does not add the route-policy parity still tracked in #1126/#1217. HTML GET navigation retains the existing interstitial.

The browser client’s explicit fetch helper recognizes the headers without consuming the response body, including HEAD responses. It retries only GET/HEAD once and never replays a mutation. Legacy validators without version-1 metadata return to the application without recovery. Cross-origin access still requires the site’s approved credentialed CORS policy and exposure of x-wd-clearance, x-wd-challenge, x-wd-challenge-reason, and x-wd-challenge-recoverable; the validator does not grant CORS access on its own.

Everything lives on the Enforcement page (sidebar → Enforcement), which is a set of routed sub-pages rather than one long scroll:

Tab What you do there
Overview (/enforcement) switch between Monitor and Enforce, read the readiness checks, and see what the loop did
Policy (/enforcement/policy) scope token-enforced routes, set each route’s minimum trust grade, and allow tokenless clients
Actions (/enforcement/actions) Response Actions
Setup (/enforcement/setup) the one-time wiring, in three steps: WAF connections, browser verification, edge validator
History (/enforcement/history) the audit log, and the way back to an earlier configuration

The split matters for finding things: the wiring you touch once is on Setup, the controls that decide what is protected are on Policy, and the switch that makes any of it live is on Overview. A half-configured organization is told so on Overview, with a link into Setup, so an unfinished install is visible from the page you land on.

Getting here is also a step on the onboarding checklist, immediately after seeing your first detection, since the question of what should happen to that traffic only exists once you have caught some. The step completes on evidence that you engaged with the decision, not on flipping to Enforce, so nothing pushes you into blocking traffic before your preconditions pass.

Mode Behavior
Monitor (default) WebDecoy generates would-enforce signals but pushes and blocks nothing. Review here first.
Enforce Live enforcement: the clearance gate refuses requests without valid clearance on scoped routes. WAF rules from Response Actions are a separate switch and are currently withheld until scorer calibration.

On Setup, in the Browser verification step:

  • Site key: your organization ID; publishable, used by the client to mint tokens.
  • Turnstile attestation: optional, and the only way a session can reach the highest trust grade. See Device Attestation.

In the WAF connections step, once Cloudflare is connected:

  • Cloudflare zone check (Test rule permissions): a preflight that creates and removes a test rule to verify the connection. It changes no live traffic.

On Policy:

  • Token-enforced routes: path patterns (e.g. /checkout/*) where the gate applies. Scope it to what your protection covers: login, checkout, the endpoints being scraped. Everything else is untouched, so normal browsing carries zero friction.
  • Minimum trust per route: how much positive human evidence a token must carry on that path, covered next.

A valid token is the floor, not the ceiling. Every route carries a minimum grade, set from the selector on its row, and each grade states what it asks of a real visitor:

Minimum What a visitor has to present
Browser check (default) nothing extra. Every real browser passes without noticing, and clients that cannot run JavaScript are still refused, which is what scoping the route already does.
Human signals one positive human signal: a browser-integrity check, interaction cadence, or browser-like TLS. Most real visitors qualify silently.
Verified challenge a passed Turnstile or Apple Private Access Token challenge. Anyone who has not already passed one is challenged before they get in.

Three properties are worth knowing before you raise a bar:

  • No minimum accepts any valid token, including ones minted before grades existed, so routes you scoped earlier are unaffected until you set a grade on them.
  • Evidence only ever raises a grade. Passing a challenge can lift a visitor; nothing they do afterwards lowers what they already earned.
  • A bot-like threat score caps the grade. Verified challenge needs a threat score of 40 or below and Human signals 60 or below, so a client that looks automated cannot buy its way onto a graded route by passing a challenge.

Legitimate clients that never run a browser pass the gate through two allowlist paths, both checked before the token requirement:

  • Verified bots: checkboxes by what a bot does (search, assistants acting for a person, AI training crawlers, link previews, and more) under Enforcement → Policy → Access exceptions. Only bots the platform or reverse DNS has verified qualify, so a cloud VM claiming to be Googlebot in its User-Agent does not. See Clearance Enforcement. A cloud VM claiming to be Googlebot fails both checks.
  • Machine service tokens: per-client credentials for your partners, monitors, and jobs, sent in a request header. Each token is shown once at creation; revoking one cuts off that client immediately with no shared blast radius.

There is deliberately no IP-range allowlist: proof, not provenance.

  • Automatic: a decoy hit carrying a clearance cookie denies the actor. This is the closed loop: deterministic honeypot evidence, not a behavioral guess.
  • Manual: every actor detail page has Deny actor / Remove deny controls.
  • API:
GET/PUT /api/organizations/{organization_id}/enforcement/mode
GET/POST /api/organizations/{organization_id}/enforcement/denylist
DELETE /api/organizations/{organization_id}/enforcement/denylist/{device_fp}
GET/POST /api/organizations/{organization_id}/enforcement/routes
PATCH /api/organizations/{organization_id}/enforcement/routes/{route_id}
DELETE /api/organizations/{organization_id}/enforcement/routes/{route_id}

PATCH on a route is how a minimum trust grade is changed. It is a distinct endpoint on purpose: re-posting an existing pattern with a new grade returns the stored row untouched, so the bar would appear to move while nothing was written.

A detection flyout can deny the adversary it is describing, without a detour through the actor page first.

When a deny is not offered, the reason is stated rather than the control quietly disappearing. Either the actor has never been seen carrying a wd_clearance token, so there is no clearance identity to lock out, or its fingerprint is shared by unrelated clients and a deny would lock out whoever else arrives under it.

History holds an append-only record of every enforcement change: mode flips, route scope, trust grades, allowlist toggles, credentials, and automatic decoy denies. It can be filtered by kind of change and narrowed to the last 24 hours, 7 days, or 30 days, and it distinguishes “nothing has ever happened” from “nothing matches this filter”.

Rows whose change left a saved configuration offer Restore this configuration, which puts the earlier policy back. Two boundaries are deliberate:

  • It restores policy only: mode, scoped routes with their trust grades, and the crawler allowlist, each including any site’s own override. Signing keys, machine credentials and the deny-list are excluded, because bringing those back would reverse a security decision rather than a configuration one. An undo that un-revokes a credential or un-denies an actor is worse than no undo.
  • Restoring is itself undoable. The current configuration is captured before the restore is applied.

Before you confirm, the dialog lists what going back changes against the configuration that is live now: which paths are added or removed, which start or stop refusing, which sites change mode, and what the crawler exemptions become. The same list is written on the History row once the restore is done, so what you agreed to and what happened are one record. The Enforce switch asks the same way: instead of a count of protected paths, it lists each path that starts refusing and what it refuses.

The restore is applied in one transaction. If it fails, nothing changed, and the page says so rather than reporting a partial apply as a clean one.

For the full per-request decision order and edge validator deployment, see Clearance Enforcement.

Fingerprint and IP rules pushed by Response Actions remain the right tool for datacenter and scripted bots, whose TLS stacks stand out and where a fingerprint block is safe. Session clearance is the gate for browser-shaped traffic: the residential rotators that no fingerprint or IP rule can block without collateral. The two layers run together.


  • Response Actions: WAF-rule automation for the datacenter layer
  • Actors: the identity model, and where deny controls live
  • Decoy Links: the ground truth that drives revocation