CONCEPT Cited by 1 source
Path enumeration attack¶
Definition¶
A path enumeration attack is the reconnaissance technique
of systematically requesting URLs against a target to discover
hidden, private, or unlinked resources — by observing which
responses are 200 OK / redirects (resource exists) versus
404 Not Found (resource does not exist).
The attack class includes:
- Directory enumeration: guessing
/admin,/backup,/.git/config,/wp-admin/,/phpmyadmin/, etc. - File enumeration: guessing filename patterns like
backup.sql,config.old,dump.tar.gz,.env.bak. - ID enumeration: walking sequential IDs like
/users/1,/users/2,/users/3to discover private user profiles. - Dictionary attack: running a wordlist (e.g. SecLists, DirBuster, gobuster wordlists) against the target.
The attack exploits the fact that a server's response to
"does this path exist?" is often observable — different
response codes, response times, or content lengths reveal
membership in the set of real paths without needing to
authenticate or exploit any vulnerability.
Why membership checks matter¶
Every public server must answer "does this path exist?" on
every request to return a 404 or serve content. An attacker
with a wordlist of likely paths can drain this signal.
The defensive properties the server wants:
- Low information leakage:
404for non-existent paths should look identical (response code, body, timing) to404for forbidden paths. - No timing side-channel:
200and404paths should take similar wall-clock time. Otherwise attackers can distinguish cache-hit real paths from reject-fast fake paths. - Rate limits: cap request rate per source to slow enumeration.
- Bot management: detect enumeration by pattern (many
404s from one source, wordlist-shaped paths) and challenge / block. - Canary paths: include known-bait paths that trigger alerts if hit.
Canonical Vercel framing¶
Vercel's 2026-04-21 routing post names the attack class as a second-order motivator for the routing service's hot-path membership check:
"Before serving a request, the routing service consults this JSON file and checks if the path exists. If it doesn't, we immediately return a 404. This early check ensures we only fetch documents from storage when we're sure they exist. [...] This prevents unnecessary requests to storage and protects against enumeration attacks, where attackers try to discover hidden files by guessing URLs."
(Source: sources/2026-04-21-vercel-how-we-made-global-routing-faster-with-bloom-filters.)
The primary motivator is don't hit storage unnecessarily (performance). The secondary motivator is don't let storage leak membership via response timing or error shape (security). A Bloom-filter membership check on the hot path delivers both: fast negative on non-existent paths + uniform response shape to the attacker.
Structural defences¶
1. Membership check before storage fetch¶
The Vercel move. Check a compact in-memory filter before
reaching to the authoritative (slower, potentially
membership-leaking) store. Uniform response shape regardless
of whether the filter was consulted or skipped — same 404
for non-existent paths whether they're filtered or fetched-
then-404'd.
2. Authenticated membership¶
Hidden resources should be behind authentication, not just obscurity. A path's secrecy is "security through obscurity" and an attacker with enough patience always finds it.
3. Non-sequential identifiers¶
Use NanoIDs, UUIDs, ULIDs for resource IDs instead of sequential integers. Makes ID enumeration statistically impossible even if endpoint is unauthenticated. Complementary to concepts/nanoid-identifier.
4. Rate limiting and bot detection¶
A human user does not request 10,000 unique paths per minute. Bot-management products (Cloudflare Bot Management, Vercel BotID, Kasada) flag enumeration signatures.
5. robots.txt is not a defence¶
robots.txt tells compliant crawlers what not to crawl.
Attackers use it as a reconnaissance hint — paths listed
in robots.txt are the ones worth enumerating.
6. Consistent timing¶
If /real-path serves from a cache in 10 ms and
/fake-path 404s in 2 ms, the attacker can distinguish them
by timing alone. Membership-check-then-storage-fetch has the
same timing for both cases (filter check dominates) — which
is one reason Vercel's Bloom-filter substitution also helps
security.
7. 404-as-403 opacity¶
Some systems return 404 uniformly for both "doesn't exist"
and "exists but you can't see it" to prevent inferring
membership via authorisation signals. Cost: legitimate users
get an unhelpful 404 instead of a useful 403.
Related attack classes¶
- Directory traversal (
../,..\\) — different class; exploits path-parsing bugs to read files outside the web root. Mitigation is parsing hygiene, not membership checks. - Forced browsing — requesting URLs the application doesn't link but hasn't protected (same root cause as enumeration, different name).
- Subdomain enumeration — DNS-level path enumeration. Same reconnaissance shape; different layer.
Seen in¶
-
sources/2026-04-21-vercel-how-we-made-global-routing-faster-with-bloom-filters — Canonical wiki introduction. Vercel's Bloom-filter membership check on the routing-service hot path doubles as enumeration-attack defence: the response to a guessed path is a uniform, storage-free
404rather than a storage-timing-leaking fetch. -
concepts/defense-in-depth — Layered defence; path enumeration defence sits alongside auth, rate limiting, bot management, and ID non-sequentialing.
-
concepts/attack-surface-minimization — Don't expose what you don't need to.