OWASP Secure Coding Cheat Sheets: Bot Management and Anti Automation Cheat Sheet

# Bot Management and Anti-Automation Cheat Sheet

## Introduction

Modern web applications face a continuous stream of automated traffic that is not a Distributed Denial of Service event but is still abusive: credential stuffing, content scraping, inventory hoarding (scalping), fake account creation, gift-card enumeration, card testing, fake reviews, click fraud, and skewed analytics. The OWASP **Automated Threats to Web Applications** project (OAT-001 through OAT-021) catalogues these patterns.

This cheat sheet provides defensive guidance that goes beyond the [Credential Stuffing Prevention Cheat Sheet](Credential_Stuffing_Prevention_Cheat_Sheet.md) and addresses the full spectrum of automated abuse. It focuses on architecture, signals, response strategy, and CAPTCHA alternatives.

The objective is **not to block all bots** (search engine crawlers, monitoring agents, and accessibility tools are legitimate) but to raise the cost of abusive automation while keeping legitimate users and bots unaffected.

## Common Threats and Risks

- **OAT-008 Credential Stuffing** — replaying breached username/password pairs.
- **OAT-011 Scraping** — large-scale content, price, or PII extraction.
- **OAT-005 Scalping / Inventory Hoarding** — buying limited stock for resale.
- **OAT-019 Account Creation** — fake accounts at signup endpoints.
- **OAT-012 Cashing Out** — using stolen accounts to extract value.
- **OAT-001 Carding** — testing stolen card numbers via low-value purchases.
- **OAT-003 Ad Fraud** — fake clicks and impressions.
- **OAT-002 Token Cracking** — brute-forcing gift cards, vouchers, coupons.
- **OAT-015 Denial of Inventory** — adding items to cart to deplete stock.
- **OAT-014 Vulnerability Scanning** — automated probing for weaknesses.
- **Skewed business metrics** — bots polluting A/B tests, recommendations, fraud models.
- **Privacy violations** — over-collecting fingerprinting data to defend against bots.

## Threat Modeling Before Controls

Before adding tooling, identify which OAT categories apply to your application and which endpoints are at risk. A login form, a search page, a checkout, and a public API have very different threat profiles and defenses.

| Endpoint type | Primary OAT risk | Suggested first control |
|---|---|---|
| Login | OAT-008 Credential Stuffing | Rate limit + breached-password check + MFA |
| Signup | OAT-019 Account Creation | Email/phone verification + velocity limits |
| Search / catalog | OAT-011 Scraping | Rate limit per identity + behavioral signal |
| Checkout / cart | OAT-005 Scalping, OAT-001 Carding | Queue + purchase limits + 3D Secure |
| Public API | OAT-011, OAT-014 | API keys + per-key quotas + signed requests |
| Comments / reviews | OAT-020 Account Aggregation, spam | Reputation + delayed publishing |

## Layered Defense Architecture

A single control is brittle. Combine controls at three layers:

1. **Edge layer** — CDN, WAF, or anti-bot service: IP reputation, ASN filtering, TLS fingerprint (JA3/JA4), HTTP/2 fingerprint, basic rate limits.
2. **Application layer** — session-aware rate limits, identity-bound quotas, behavioral signals, honeypots, CAPTCHA challenges.
3. **Backend / business layer** — anomaly detection on transactions, account-velocity rules, fraud scoring, async review queues.

A request that looks human at one layer (good IP, valid CAPTCHA) may still fail at another (10 checkouts in 30 seconds with different cards).

## Rate Limiting and Quotas

Rate limiting is the foundational control. Apply it at multiple keys, not just IP.

- **Per IP** — coarse, defeated by residential proxy networks but still useful as a floor.
- **Per session / cookie** — defeated by cookie clearing, useful against unsophisticated bots.
- **Per authenticated identity** — most reliable; applies after login.
- **Per endpoint** — the login endpoint deserves a tighter limit than the home page.
- **Per ASN or geo** — useful when traffic from datacenter ASNs is unexpected.

Use a token-bucket or sliding-window algorithm. Avoid fixed-window counters: they allow bursts at boundary times.

A correct login-endpoint rate limit applies **two independent buckets**, both of which must be under their threshold for the request to pass:

- **Per-username bucket** — limits attempts against any single account regardless of source IP. Defends a targeted account from a distributed attack.
- **Per-IP (or per-IP+ASN) bucket** — limits the volume of attempts originating from one source against any account. Defends against credential-stuffing sweeps that try one password per account.

A common mistake is to use a single bucket keyed on the *combination* of IP and username (e.g., `login:<ip>:<user>`). This creates one bucket per pair, which means a single IP can attempt the threshold against an unlimited number of usernames before any limit fires — exactly the credential-stuffing pattern you were trying to stop. Always check the two buckets separately.

When a limit is hit, return a generic `429 Too Many Requests`. Avoid `Retry-After` values precise enough to schedule retries against. Do not include diagnostic detail (which bucket fired, remaining attempts) — that information is useful only to attackers tuning their tooling.

## Device and Network Fingerprinting (Privacy-Aware)

Fingerprinting helps detect bots that rotate IPs but reuse client environments. Use **passive, network-level** signals first; resort to client-side fingerprinting only when necessary.

Network signals (no client cooperation needed):

- **JA3 / JA4** — TLS ClientHello fingerprint. Headless tooling often produces uncommon JA3 values.
- **HTTP/2 fingerprint (Akamai)** — frame ordering, settings, priorities.
- **Client Hints (`Sec-CH-UA-*`)** — declared but verifiable against TLS fingerprint.

Browser-side signals (last resort, with consent where required):

- WebGL renderer string, canvas hash, font list, audio context — strong but invasive.
- Page-level behavioral telemetry (mouse paths, scroll, focus) — collect only on sensitive flows.

**Privacy guidance:**

- Document fingerprinting in your privacy notice; some jurisdictions (EU/UK ePrivacy, CCPA) require disclosure or opt-out.
- Hash or truncate any fingerprint before storage; do not retain raw values that enable re-identification.
- Set short retention windows (hours to days) for anti-bot signals — long enough to detect, short enough to limit surveillance risk.
- Avoid fingerprinting authenticated, low-risk traffic (a logged-in user reading their own profile does not need to be fingerprinted again).

## CAPTCHA and Its Modern Alternatives

Visible CAPTCHAs (image grids, distorted text) are accessibility-hostile, machine-solvable by ML, and outsourced to human solver farms for fractions of a cent per solve. Treat them as a **last-resort step-up**, not a primary defense.

Prefer the following alternatives or layer them:

- **Cryptographic attestation tokens** — Privacy Pass (RFC 9576), Apple Private Access Tokens, and emerging