AI Bot User-Agent Spoofing: How Attackers Evade WAFs During Mass Scans
The Signal: What Actually Happened
Data from Known Agents revealed a sharp, anomalous spike in traffic purporting to be from legitimate AI crawlers. The user-agent strings—ClaudeBot, GPTBot, PerplexityBot—looked correct. The IP addresses did not. These weren't the documented, reverse-DNS-verifiable origin servers of Anthropic, OpenAI, or Perplexity. They were random VPS endpoints, residential proxies, and Tor exit nodes firing off requests at a rate no polite crawler would ever use.
The payload told the real story. These requests weren't fetching robots.txt or politely indexing public content. They were probing for exposed .env files, testing authentication bypasses on admin panels, and iterating through known CVEs in popular WordPress plugins. Someone had weaponized the reputation of AI bots to run a mass vulnerability scan.
This isn't a theoretical attack. It's a live, observable shift in how opportunistic attackers are routing around simple user-agent-based allow/block rules. The core insight is brutally simple: if your WAF or rate limiter has an implicit trust relationship with a user-agent string, you've handed over a skeleton key.
The Anatomy of a Spoofed Scan
To understand the attack, you need to see the full request context. A legitimate ClaudeBot hit looks something like this:
GET /blog/rss-newsletter-agent-cron-cloudflare-workers HTTP/1.1
Host: fdecoach.com
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ClaudeBot/1.0; +https://www.anthropic.com/claude/bot
Accept: */*
A spoofed probe, in contrast, carries the same user-agent but targets a completely different surface area:
GET /.env HTTP/1.1
Host: fdecoach.com
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ClaudeBot/1.0; +https://www.anthropic.com/claude/bot
Accept: */*
The request path is the smoking gun. No legitimate AI crawler scans for environment files. The attack pattern is a classic spray-and-pray: hit every domain in a target list with a common wordlist of sensitive paths, but dress the request in a user-agent that many security teams have explicitly allowlisted to avoid blocking AI-driven traffic that might benefit their SEO.
The Full Flow
Here's how the scan infrastructure typically chains together:
The attack succeeds because the decision gate at the WAF layer uses a single, easily forged signal to classify the traffic as benign.
Why This Bypass Works: The Trust Paradox
Engineers have been conditioned to treat certain user-agents as trustworthy. This makes sense in a world where Googlebot's traffic directly correlates to search visibility. Blocking a legitimate AI crawler could theoretically impact how your content surfaces in AI-powered search summaries. The business pressure to keep these crawlers unblocked is real.
The problem is that the user-agent header is fundamentally a client-supplied, unauthenticated string. Relying on it for any security decision violates a core principle: never trust input you haven't verified through an out-of-band channel.
Here's the trust model most teams are running implicitly:
| Signal | Trust Level | Reality |
|---|---|---|
| User-Agent string matches known bot | High | Trivial to spoof |
Request path is /robots.txt | Medium | Legitimate bots fetch this first |
Request path is /wp-admin | Low | Immediate block candidate |
| IP reverse-DNS matches bot's domain | Very High | Hard to spoof, rarely checked |
The gap between "User-Agent matches known bot" and "IP reverse-DNS matches bot's domain" is where the mass scan operates. Most teams stop at the first check.
Practical Detection Engineering: Finding the Fakes
You don't need a vendor solution to start catching these. If you've got access to your edge logs, you can write detection logic today. The goal is to find requests where the user-agent claims to be a known crawler but the behavior or origin doesn't match.
Step 1: Verify the IP
Legitimate AI crawlers publish their IP ranges or have reverse-DNS entries that map back to their domain. For ClaudeBot, the reverse-DNS should resolve to a hostname under anthropic.com. For GPTBot, it's openai.com. Write a quick verification script:
import socket
def verify_bot_ip(ip: str, expected_domain: str) -> bool:
try:
hostname, _, _ = socket.gethostbyaddr(ip)
return hostname.endswith(expected_domain)
except socket.herror:
return False
# Example: Check if an IP claiming to be ClaudeBot actually belongs to Anthropic
if not verify_bot_ip(request.ip, "anthropic.com"):
log_and_flag(request)
This check is fast, runs inline, and catches the vast majority of spoofed traffic. Residential proxy IPs won't resolve to anthropic.com. Neither will random VPS instances.
Step 2: Rate and Path Analysis
Even without IP verification, the request pattern gives them away. A legitimate crawler has a characteristic rhythm: it fetches robots.txt, respects Crawl-Delay directives, and spreads requests across your entire site. A vulnerability scanner hammers a specific set of paths at high frequency.
Set up a simple heuristic in your log pipeline:
SELECT
client_ip,
user_agent,
COUNT(*) as request_count,
COUNT(DISTINCT request_path) as unique_paths
FROM edge_logs
WHERE user_agent LIKE '%ClaudeBot%'
AND timestamp > NOW() - INTERVAL '5 minutes'
GROUP BY client_ip, user_agent
HAVING request_count > 100
OR unique_paths < 3;
A real ClaudeBot will show moderate request counts across many unique paths. A scanner will show high counts concentrated on a handful of sensitive endpoints.
Step 3: Challenge Suspicious Sessions
When you flag a session as suspicious, don't just block it—that teaches the attacker which IPs you've identified. Instead, issue a silent challenge. Drop a cookie requirement or inject a JavaScript challenge. Legitimate crawlers don't execute JavaScript and won't be affected. Automated scanners using raw HTTP libraries will fail the challenge, and you can log the failure without tipping your hand.
Building a Low-Friction Defensive Layer
If you're running a production workload, you need this logic baked into your edge layer. The architecture is straightforward:
This adds a single reverse-DNS lookup to the hot path for bot-claimed requests. The latency cost is minimal if you cache the results. A local in-memory cache with a 1-hour TTL for verified IPs keeps the overhead near zero for repeat visitors.
For teams building custom detection pipelines, this same pattern applies whether you're processing edge logs in a Gemini-powered sentiment dashboard or routing traffic through a Cloudflare Worker. The verification step is the same; only the integration point changes.
The Offensive Engineer's Perspective
Understanding the attacker's tooling makes the defense obvious. Most mass scanners are built on tools like nuclei with custom user-agent flags or simple Python scripts using the requests library. The attacker's workflow is:
- Generate a target list (Shodan searches, certificate transparency logs, DNS brute-force)
- Load a wordlist of sensitive paths (
.env,.git/config,/wp-json/wp/v2/users) - Set
User-Agent: ClaudeBot/1.0in the request header - Route through a proxy pool to distribute the source IPs
- Parse responses for secrets, version headers, or exposed configuration
The entire operation hinges on step 3 being enough to bypass the first layer of defense. As a forward deployed engineer, you can replicate this exact workflow in a controlled red-team exercise. Build a job application autofill extension or a personal finance categorizer first to get comfortable with shipping artifacts that touch external APIs. The same request-manipulation skills apply directly to security testing.
A Balanced Take: The Real Risk
This isn't a sophisticated APT technique. It's a low-effort, high-reward tactic that works because the defense community has been slow to update its mental model around AI crawlers. The risk is amplified by the fact that many organizations have explicitly added allowlist rules for these user-agents in the last 12 months without adding the corresponding verification step.
The fix isn't to block AI crawlers. The legitimate ones provide value, and the business case for allowing them is sound. The fix is to stop treating the user-agent string as an identity assertion and start treating it as an unverified claim that requires corroboration.
For FDEs specifically, this is a perfect interview signal. When you're preparing for the FDE interview loop, being able to walk through this exact scenario—"How would you detect and mitigate AI bot spoofing?"—demonstrates the kind of practical, systems-level thinking that separates signal from memorization. It shows you understand the trust boundaries in distributed systems and can design defenses that work in production, not just on a whiteboard.
FAQ
Q: Can't I just block any request with a path like /.env regardless of user-agent?
Yes, and you should. A well-configured WAF should have path-based rules that catch common sensitive-file probes. The user-agent spoofing becomes an issue when your WAF has an allowlist rule that skips those checks for certain user-agents. The attack exploits the ordering of your rule evaluation.
Q: What's the performance impact of reverse-DNS lookups on every request? Non-trivial if done synchronously on every request. Cache aggressively. Verified bot IPs rarely change. A 1-hour cache with a fast fallback (treat cache misses as unverified) keeps the 99th percentile latency under 5ms.
Q: Are residential proxy IPs ever going to reverse-DNS to a legitimate bot domain?
No. Residential proxy providers use consumer ISP IPs. These will never have reverse-DNS entries pointing to anthropic.com or openai.com. This makes the reverse-DNS check extremely high-signal.
Q: What if the attacker uses the actual IP ranges of a legitimate bot? That's a fundamentally different, much harder attack. It would require compromising the bot's infrastructure or running a man-in-the-middle between the bot and your server. At that point, you're not dealing with a mass vulnerability scanner; you're dealing with a targeted adversary, and your threat model should adjust accordingly.
Q: Should I share this intelligence with my team? Absolutely. The Known Agents data is public, and the detection logic is straightforward to implement. The fastest way to close this gap is to add a reverse-DNS verification step to your existing bot management rules and share the before/after metrics with your security team.
Want to build like a Forward Deployed Engineer?
FDE Coach is a cohort-based program in frontend, backend, AWS, and AI. Build real products and get referred to 200+ hiring partners.
Explore the program