- name
- vercel-firewall
- description
- Vercel Firewall and security expert guidance. Use when configuring DDoS protection, WAF rules, rate limiting, bot filtering, IP allow/block lists, OWASP rulesets, Attack Challenge Mode, or any security configuration on the Vercel platform.
- metadata
- {"priority":5,"docs":["https://vercel.com/docs/security/vercel-firewall"],"sitemap":"https://vercel.com/sitemap/docs.xml","pathPatterns":[".vercel/firewall/**"],"bashPatterns":["\\bvercel\\s+firewall\\b"],"promptSignals":{"phrases":["rate limit","rate limiting","firewall","WAF","DDoS protection"],"minScore":6}}
# Vercel Firewall
You are an expert in the Vercel Firewall — a multi-layered security solution with automatic DDoS protection, a customizable Web Application Firewall (WAF), bot management, and rate limiting.
## Architecture & Rule Execution Order
1. DDoS mitigation rules (automatic, platform-wide)
2. WAF IP blocking rules
3. WAF custom rules (in priority order)
4. WAF Managed Rulesets (OWASP, Bot Protection, AI Bots)
Changes propagate globally in under **300ms**. No redeployment required.
## DDoS Protection (Automatic, All Plans)
- Layer 3/4 mitigation (automatic, always on)
- Layer 7 protection (proprietary, tailored to web apps)
- **Protectd**: Vercel's DoS mitigation infrastructure analyzes ~550K events/sec globally with median mitigation time of **2.5 seconds**
- 40x faster detection with real-time stream processing
- Handles 1B+ suspicious TCP connections per week
- Proven to mitigate 1.37 Tbps attacks with zero downtime
No configuration needed — DDoS protection is always active.
## WAF Custom Rules
### Rule JSON Structure
```json
{
"name": "Block WordPress scanners",
"description": "Block common WordPress probe paths",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "path",
"op": "re",
"value": "^/wp-(admin|login|content|includes)/"
}
]
}
],
"action": {
"mitigate": {
"action": "deny"
}
}
}
```
**Logic**: Each object in `conditionGroup` is an **OR** group. Conditions within a single group are **AND**ed. Multiple groups are **OR**ed.
### Condition Types (25 available)
| Type | Description | Extra Fields |
|------|-------------|--------------|
| `path` | URL path | |
| `method` | HTTP method | |
| `host` | Hostname | |
| `ip_address` | Client IP (supports CIDR) | |
| `user_agent` | User-Agent string | |
| `header` | Request header value | `key` (header name) |
| `query` | Query string parameter | `key` (param name) |
| `cookie` | Cookie value | `key` (cookie name) |
| `geo_country` | ISO country code (e.g., `US`) | |
| `geo_continent` | Continent code (e.g., `NA`) | |
| `geo_country_region` | State/province code | |
| `geo_city` | City name | |
| `geo_as_number` | ASN | |
| `ja4_digest` | JA4 TLS fingerprint | |
| `ja3_digest` | JA3 TLS fingerprint | |
| `target_path` | Resolved path after routing | |
| `route` | Matched route pattern | |
| `raw_path` | Raw unparsed path | |
| `region` | Vercel edge region code | |
| `protocol` | http/https | |
| `scheme` | URL scheme | |
| `environment` | Deployment environment | |
| `bot_name` | Specific bot name | |
| `bot_category` | Bot category | |
| `server_action` | Next.js Server Action ID | |
### Condition Operators
| Op | Meaning |
|----|---------|
| `eq` | Equals |
| `neq` | Not equals |
| `re` | Regex match |
| `pre` | Starts with |
| `suf` | Ends with |
| `sub` | Contains |
| `inc` | In array |
| `ninc` | Not in array |
| `ex` | Exists |
| `nex` | Not exists |
| `gt` / `gte` | Greater than (or equal) |
| `lt` / `lte` | Less than (or equal) |
Additional optional fields: `neg: true` negates the condition, `key` required for `header`/`query`/`cookie` types.
### Mitigation Actions
| Action | Description |
|--------|-------------|
| `log` | Log only, allow traffic |
| `deny` | Block request (403) |
| `challenge` | JavaScript browser challenge |
| `bypass` | Skip all subsequent WAF rules |
| `rate_limit` | Apply rate limiting (requires `rateLimit` config) |
| `redirect` | Redirect (requires `redirect` config) |
### Persistent Actions
By default each request is evaluated individually. With **persistent actions**, rules are applied to all matching requests for a customizable duration (`actionDuration`), allowing the firewall to remember malicious behavior and block it earlier in the lifecycle.
### Action Options
```json
{
"action": {
"mitigate": {
"action": "deny",
"actionDuration": "1h",
"bypassSystem": false,
"logHeaders": ["user-agent", "x-forwarded-for"],
"redirect": {
"location": "https://example.com/blocked",
"permanent": false
}
}
}
}
```
## Practical Rule Examples
### Block Sanctioned Countries
```json
{
"name": "Block OFAC Sanctioned Countries",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "geo_country",
"op": "inc",
"value": ["CU", "IR", "KP", "RU", "SY"]
}
]
}
],
"action": {
"mitigate": { "action": "deny" }
}
}
```
### Require API Key Header on /api/ Routes
```json
{
"name": "Require API Key",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "header",
"op": "nex",
"key": "x-api-key"
},
{
"type": "path",
"op": "pre",
"value": "/api/"
}
]
}
],
"action": {
"mitigate": { "action": "deny" }
}
}
```
### Block by JA4 TLS Fingerprint
```json
{
"name": "Block Known Malicious JA4",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "ja4_digest",
"op": "eq",
"value": "t13d1516h2_8daaf6152771_b0da82dd1658"
}
]
}
],
"action": {
"mitigate": { "action": "deny", "actionDuration": "1h" }
}
}
```
### Block Datacenter ASNs
```json
{
"name": "Block Known Datacenter ASNs",
"active": true,
"conditionGroup": [
{
"conditions": [
{
"type": "geo_as_number",
"op": "inc",
"value": ["14618", "16509", "15169"]
}
]
}
],
"action": {
"mitigate": { "action": "deny" }
}
}
```
### Challenge cURL Requests
```json
{
"name": "Challenge cURL",
"active": true,
"conditionGroup": [
{
"conditions": [
{ "type": "user_agent", "op": "re", "value": "^curl/" }
]
}
],
"action": {
"mitigate": { "action": "challenge" }
}
}
```
## Rate Limiting
### Rate Limit Rule
```json
{
"name": "API Rate Limit - 100 req/min",
"active": true,
"conditionGroup": [
{
"conditions": [
{ "type": "path", "op": "pre", "value": "/api/" }
]
}
],
"action": {
"mitigate": {
"action": "rate_limit",
"rateLimit": {
"algo": "fixed_window",
"window": 60,
"limit": 100,
"keys": ["ip"],
"action": "deny"
}
}
}
}
```
### Login Endpoint Protection
```json
{
"name": "Login Rate Limit",
"active": true,
"conditionGroup": [
{
"conditions": [
{ "type": "path", "op": "eq", "value": "/api/auth/login" },
{ "type": "method", "op": "eq", "value": "POST" }
]
}
],
"action": {
"mitigate": {
"action": "rate_limit",
"rateLimit": {
"algo": "fixed_window",
"window": 60,
"limit": 10,
"keys": ["ip"],
"action": "challenge"
}
}
}
}
```
### Rate Limit Configuration Options
| Field | Type | Description |
|-------|------|-------------|
| `algo` | string | `"fixed_window"` (all plans) or `"token_bucket"` (Enterprise) |
| `window` | number | Seconds. Min 10, max 600 (Pro), max 3600 (Enterprise) |
| `limit` | number | Max requests per window |
| `keys` | array | Count per: `"ip"`, `"ja4"`, `"user_agent"`, custom headers (Enterprise) |
| `action` | string | When exceeded: `"deny"`, `"log"`, `"challenge"` |
When exceeded with `deny`, returns HTTP 429 with `X-RateLimit-Limit` and `X-RateLimit-Remaining` headers.
## Bot Management
### Bot Protection (GA — Free on All Plans)
Heuristics-based detection that challenges non-browser bot traffic without disrupting verified webhook providers. Formerly "Bot Filter" during beta — renamed to Bot Protection at GA. Enable in log-only mode first to preview traffic impact:
```json
{
"action": "managedRules.update",
"id": "bot_protection",
"value": { "active": true, "action": "challenge" }
}
```
> **Note**: The older `bot_filter` ID is deprecated. Use `bot_protection` in new configurations.
### AI Bot Blocking
Block known AI crawlers (GPTBot, ClaudeBot, etc.):
```json
{
"action": "managedRules.update",
"id": "ai_bots",
"value": { "active": true, "action": "deny" }
}
```
### Allow a Specific Bot (Bypass Rule)
Place this higher in priority than Bot Protection managed rules:
```json
{
"name": "Allow My Monitoring Bot",
"active": true,
"conditionGroup": [
{
"conditions": [
{ "type": "user_agent", "op": "eq", "value": "MyMonitorBot/1.0" }
]
}
],
"action": {
Ver no GitHub