vercel-firewall

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.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "vercel-firewall" with this command: npx skills add vercel-labs/vercel-plugin/vercel-labs-vercel-plugin-vercel-firewall

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

{
  "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 ANDed. Multiple groups are ORed.

Condition Types (25 available)

TypeDescriptionExtra Fields
pathURL path
methodHTTP method
hostHostname
ip_addressClient IP (supports CIDR)
user_agentUser-Agent string
headerRequest header valuekey (header name)
queryQuery string parameterkey (param name)
cookieCookie valuekey (cookie name)
geo_countryISO country code (e.g., US)
geo_continentContinent code (e.g., NA)
geo_country_regionState/province code
geo_cityCity name
geo_as_numberASN
ja4_digestJA4 TLS fingerprint
ja3_digestJA3 TLS fingerprint
target_pathResolved path after routing
routeMatched route pattern
raw_pathRaw unparsed path
regionVercel edge region code
protocolhttp/https
schemeURL scheme
environmentDeployment environment
bot_nameSpecific bot name
bot_categoryBot category
server_actionNext.js Server Action ID

Condition Operators

OpMeaning
eqEquals
neqNot equals
reRegex match
preStarts with
sufEnds with
subContains
incIn array
nincNot in array
exExists
nexNot exists
gt / gteGreater than (or equal)
lt / lteLess than (or equal)

Additional optional fields: neg: true negates the condition, key required for header/query/cookie types.

Mitigation Actions

ActionDescription
logLog only, allow traffic
denyBlock request (403)
challengeJavaScript browser challenge
bypassSkip all subsequent WAF rules
rate_limitApply rate limiting (requires rateLimit config)
redirectRedirect (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

{
  "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

{
  "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

{
  "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

{
  "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

{
  "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

{
  "name": "Challenge cURL",
  "active": true,
  "conditionGroup": [
    {
      "conditions": [
        { "type": "user_agent", "op": "re", "value": "^curl/" }
      ]
    }
  ],
  "action": {
    "mitigate": { "action": "challenge" }
  }
}

Rate Limiting

Rate Limit Rule

{
  "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

{
  "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

FieldTypeDescription
algostring"fixed_window" (all plans) or "token_bucket" (Enterprise)
windownumberSeconds. Min 10, max 600 (Pro), max 3600 (Enterprise)
limitnumberMax requests per window
keysarrayCount per: "ip", "ja4", "user_agent", custom headers (Enterprise)
actionstringWhen 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:

{
  "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.):

{
  "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:

{
  "name": "Allow My Monitoring Bot",
  "active": true,
  "conditionGroup": [
    {
      "conditions": [
        { "type": "user_agent", "op": "eq", "value": "MyMonitorBot/1.0" }
      ]
    }
  ],
  "action": {
    "mitigate": { "action": "bypass" }
  }
}

Enable BotID (Traffic Visibility)

{ "botIdEnabled": true }

IP Allow/Block Lists

Block an IP

{
  "action": "ip.insert",
  "value": {
    "hostname": "my-site.com",
    "ip": "203.0.113.45",
    "action": "deny",
    "notes": "Malicious scraper"
  }
}

Block a CIDR Range

{
  "action": "ip.insert",
  "value": {
    "hostname": "my-site.com",
    "ip": "203.0.113.0/24",
    "action": "deny",
    "notes": "Bad actor CIDR block"
  }
}

Allow an IP (Bypass All Rules)

{
  "action": "ip.insert",
  "value": {
    "hostname": "my-site.com",
    "ip": "198.51.100.1",
    "action": "bypass",
    "notes": "Internal monitoring IP"
  }
}

IP Rule Actions

ActionEffect
denyBlock the IP
challengeServe JS challenge
logLog traffic only
bypassAllow through all rules (allowlist)

Note: hostname must match the exact domain. Add separate entries per subdomain.

OWASP Core Ruleset (CRS)

Individual CRS Rules

IDProtection
sqliSQL Injection
xssCross-Site Scripting
rceRemote Code Execution
lfiLocal File Inclusion
rfiRemote File Inclusion
sdScanner Detection
maMultipart Attack
phpPHP-specific exploits
genGeneric attack patterns
sfSession Fixation
javaJava-specific exploits

Enable OWASP Rules

{
  "action": "crs.update",
  "id": "sqli",
  "value": { "active": true, "action": "deny" }
}

Full OWASP + Bot Configuration (PUT)

{
  "firewallEnabled": true,
  "crs": {
    "sqli": { "active": true, "action": "deny" },
    "xss": { "active": true, "action": "deny" },
    "rce": { "active": true, "action": "deny" },
    "lfi": { "active": true, "action": "deny" },
    "rfi": { "active": true, "action": "deny" },
    "sd": { "active": true, "action": "log" },
    "ma": { "active": true, "action": "deny" },
    "gen": { "active": true, "action": "deny" },
    "sf": { "active": true, "action": "deny" },
    "php": { "active": false, "action": "log" },
    "java": { "active": false, "action": "log" }
  },
  "managedRules": {
    "owasp": { "active": true, "action": "deny" },
    "bot_protection": { "active": true, "action": "challenge" },
    "ai_bots": { "active": true, "action": "deny" }
  },
  "botIdEnabled": true
}

Firewall REST API

Base URL: https://api.vercel.com Auth: Authorization: Bearer <VERCEL_TOKEN> Query params: ?projectId=<id>&teamId=<id>

Endpoints

MethodPathDescription
GET/v1/security/firewall/config/activeRead current config
PATCH/v1/security/firewall/configIncremental update (add/remove/update rules)
PUT/v1/security/firewall/configFull config replacement
POST/v1/security/firewall/bypassCreate temporary bypass rule

PATCH Actions

ActionDescription
firewallEnabledEnable/disable firewall (value: boolean)
rules.insertAdd a custom rule
rules.updateUpdate rule (requires id)
rules.removeDelete rule (requires id)
rules.priorityReorder rule (requires id, value = index)
ip.insertAdd IP rule
ip.updateUpdate IP rule
ip.removeDelete IP rule
crs.updateEnable/configure OWASP CRS rule
crs.disableDisable entire CRS
managedRules.updateConfigure managed ruleset

Add a Rule via cURL

curl -X PATCH "https://api.vercel.com/v1/security/firewall/config?projectId=prj_xxx&teamId=team_xxx" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "rules.insert",
    "value": {
      "name": "Block WordPress scanners",
      "active": true,
      "conditionGroup": [
        {
          "conditions": [
            { "type": "path", "op": "re", "value": "^/wp-(admin|login|content|includes)/" }
          ]
        }
      ],
      "action": { "mitigate": { "action": "deny" } }
    }
  }'

Vercel SDK Usage

import { Vercel } from '@vercel/sdk'

const vercel = new Vercel({ bearerToken: process.env.VERCEL_TOKEN })

// Read current firewall config
const config = await vercel.security.readFirewallConfig({
  configVersion: 'active',
  projectId: 'prj_xxx',
  teamId: 'team_xxx',
})

// Add a rule
await vercel.security.updateFirewallConfig({
  projectId: 'prj_xxx',
  teamId: 'team_xxx',
  requestBody: {
    action: 'rules.insert',
    value: {
      name: 'Rate limit API',
      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' },
        },
      },
    },
  },
})

Create Temporary Bypass (Attack Challenge Mode)

curl -X POST "https://api.vercel.com/v1/security/firewall/bypass?projectId=prj_xxx&teamId=team_xxx" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "my-site.com",
    "sourceIp": "198.51.100.42",
    "ttl": 3600000,
    "note": "Temporary bypass for load testing"
  }'

vercel.json WAF Rules

Declaratively define firewall rules in vercel.json using the mitigate key:

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "routes": [
    {
      "src": "/api/(.*)",
      "missing": [
        { "type": "header", "key": "x-internal-token" }
      ],
      "mitigate": { "action": "deny" }
    },
    {
      "src": "/(.*)",
      "has": [
        { "type": "header", "key": "user-agent", "value": "(?i)^curl/" }
      ],
      "mitigate": { "action": "challenge" }
    }
  ]
}

Supported actions in vercel.json: "challenge", "deny" only. Rate limiting, log, and bypass require the Vercel Firewall dashboard at https://vercel.com/{team}/{project}/firewall or the REST API.

Attack Challenge Mode

  • Available on all plans (free)
  • Shows browser verification challenge to all visitors during active attacks
  • Legitimate bots (Googlebot, webhook providers) automatically pass through
  • Internal Function-to-Function calls within the same account bypass automatically
  • Blocked requests don't count toward CDN/traffic usage
  • Configured via dashboard only: open https://vercel.com/{team}/{project}/firewallBot ManagementAttack Challenge Mode

Plan Availability

FeatureHobbyProEnterprise
DDoS ProtectionAllAllAll
Custom Rules5401000
Rate Limiting1 rule40 rules1000 rules
Bot Protection (GA)YesYesYes
OWASP CRSYes
Token Bucket algoYes
Custom rate limit keysYes

Observability

  • Security event logs in the Firewall tab
  • IP enrichment — hover any IP in the Firewall dashboard to see ASN, location, and metadata
  • Create custom WAF rules directly from dashboard traffic charts (select "Create Custom Rule" from the actions menu)
  • Linkable to Monitoring queries for investigations
  • DDoS mitigation notifications (alerts on detection)
  • BotID traffic visibility when enabled

Official Documentation

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

plugin-audit

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.

Repository SourceNeeds Review
102.7K22.4Kvercel-labs
Automation

vercel-sandbox

No summary provided by upstream source.

Repository SourceNeeds Review
General

shadcn

No summary provided by upstream source.

Repository SourceNeeds Review