# Threat model

> Assets, actors, trust boundaries, threats with their mitigations and residual risk, and the assumptions AgentGate relies on.

Scope: the AgentGate service (one Go binary with SQLite state), its browser SDK and challenge pages, the gateway authorization endpoint, the signed-agent API, and the operator dashboard. Date: 2026-09-24.

## Assets

| Asset | Why it matters |
| --- | --- |
| Signing keys (HMAC token keys, Ed25519 receipt key) | Forged receipts, clearances or passes would admit any client |
| Site backend credentials and operator credentials | Impersonate a customer's backend or the operator |
| Customer site configuration and rule sets | Silent weakening of a customer's protection |
| Decision events and interaction features | Pseudonymous behavioural data about visitors |
| Replay state (receipts, challenges, nonces) | Losing it allows one proof to authorise many operations |
| Availability of the decision path | Enforce-mode sites fail closed when AgentGate is down |

## Actors

- **Automated clients**: scripts (no browser), headless and headed browsers driven over CDP, stealth-patched browsers, and LLM browser agents in a user's own Chrome.
- **Cooperating agents** that sign with Web Bot Auth, and agents that claim a vendor identity without signing.
- **Visitors**, including people using assistive technology, dictation, IMEs, privacy browsers, VPNs and shared networks.
- **Customers** (site owners) and **operators**; a compromised customer backend; an attacker on the network path.

## Trust boundaries

1. Browser → public SDK/challenge API: everything the browser sends (signals, proofs, traces, headers) is attacker-controlled.
2. Customer gateway/backend → gateway check / siteverify: authenticated by a site credential; original-request metadata is trusted only from that authenticated caller.
3. Nginx → AgentGate on loopback: `X-Real-IP`, `X-Forwarded-Proto` and `X-JA4` are trusted only from loopback.
4. Operator → admin API/dashboard: private network or SSH tunnel; session cookie with CSRF protection.
5. AgentGate → the Internet: key directories, published crawler ranges, IP datasets and Tor lists are fetched data, validated and size-limited, never executed.

## Threats and mitigations

| Threat | Mitigation | Residual risk |
| --- | --- | --- |
| Script submits without running the page | Proof of work bound to the form token/challenge; per-request instrumentation program needing a real DOM | A patched DOM emulator or real headless browser can answer; this raises cost, not a barrier |
| Script fabricates interaction signals | Instrumentation challenge; raw traces with timing/structure checks; cross-context and environment consistency | Replay of recorded genuine human traces is not detected |
| Browser agent in a real Chrome | Key cadence, pointer semantics (teleports, pressure, coalesced samples), agent DOM markers, human/bot/agent model | An agent injecting OS-level input or sampling human timing distributions can pass; models are trained on synthetic data |
| Token replay | Single-use receipts consumed atomically in durable storage; nonce caches for signatures; challenges single-use | Process-local rate limits reset on restart |
| Token theft / cross-site use | Tokens bound to site, action, origin, expiry and key ID; clearances bound to site and origin | A token stolen in-browser before use can be spent once within its lifetime |
| Forged original-request metadata at the gateway | Only authenticated gateway callers may supply metadata; the adapter overwrites forwarded headers and strips client-supplied AgentGate headers | A misconfigured customer gateway can still forward client headers |
| Signed-agent impersonation | RFC 9421 verification against allow-listed key directories; body digest bound on the agent API; `created`/`expires`/nonce checks | A stolen agent private key is valid until the directory rotates it |
| Header spoofing of IP/TLS | Loopback-only trust for proxy headers; direct-TLS mode computes JA4 itself | Behind a proxy without the JA4 module, TLS signals are unavailable |
| Credential leakage | Hash-only storage, reveal once, revocation and overlapping rotation; never logged | A leaked credential is valid until revoked |
| Rule-set tampering | Admin API private and authenticated; config changes audited; validation rejects malformed rules and regexes (RE2, bounded) | An operator with access can weaken rules (audited, not prevented) |
| Resource exhaustion | Body and proof size caps; issuance and verification rate limits; bounded caches and key counts; fetch timeouts | Volumetric DDoS is out of scope |
| Parser bugs | Go fuzz targets for structured fields, signature inputs, markdown, proof JSON and test signatures | Fuzzing is time-bounded |
| Dependency vulnerabilities | `govulncheck` in the release checklist | New advisories between releases |
| Accessibility harms (people wrongly blocked) | Unmeasured model and environment detectors ship in count mode; the enforcing instrument check answers a missing answer with the visible check, not a block; press-and-hold with keyboard hold and a no-interaction alternative | No real assistive-technology cohort has been measured; a wrong instrument answer is blocked, and only Chrome has been checked against the simulator |
| Privacy harms | Collect timings, counts and environment facts only; never field contents or key identities; pseudonymous source IDs; retention limits | Behavioural data is still personal data under GDPR; see the privacy notice |

## Assumptions

- The host, its root account and the state directory are trusted; SQLite files and `keys.json` are readable only by the service user.
- Operators review rule changes; the service does not defend against a malicious operator.
- Customers run `siteverify` or the gateway; the browser widget alone enforces nothing.
