external/anthropic-cybersecurity-skills/skills/securing-api-gateway-with-aws-waf/SKILL.md
Securing API Gateway endpoints with AWS WAF by configuring managed rule groups for OWASP Top 10 protection, creating custom rate limiting rules, implementing bot control, setting up IP reputation filtering, and monitoring WAF metrics for security effectiveness.
npx skillsauth add seikaikyo/dash-skills securing-api-gateway-with-aws-wafInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Do not use for network-level DDoS protection (use AWS Shield), for application logic vulnerabilities (use SAST/DAST tools), or for internal API security between microservices (use service mesh authentication and authorization).
wafv2:* and apigateway:* operationsCreate a Web ACL with AWS Managed Rules for baseline protection against OWASP Top 10 attacks.
# Create a WAF Web ACL with managed rule groups
aws wafv2 create-web-acl \
--name api-gateway-waf \
--scope REGIONAL \
--default-action '{"Allow":{}}' \
--visibility-config '{
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "api-gateway-waf"
}' \
--rules '[
{
"Name": "AWSManagedRulesCommonRuleSet",
"Priority": 1,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "CommonRuleSet"
}
},
{
"Name": "AWSManagedRulesKnownBadInputsRuleSet",
"Priority": 2,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesKnownBadInputsRuleSet"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "KnownBadInputs"
}
},
{
"Name": "AWSManagedRulesSQLiRuleSet",
"Priority": 3,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesSQLiRuleSet"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "SQLiRuleSet"
}
},
{
"Name": "AWSManagedRulesAmazonIpReputationList",
"Priority": 4,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAmazonIpReputationList"
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "IPReputationList"
}
}
]'
Configure rate-based rules to throttle excessive API requests per IP address.
# Get the Web ACL ARN and lock token
WEB_ACL_ARN=$(aws wafv2 list-web-acls --scope REGIONAL \
--query "WebACLs[?Name=='api-gateway-waf'].ARN" --output text)
# Update Web ACL to add rate limiting rule
aws wafv2 update-web-acl \
--name api-gateway-waf \
--scope REGIONAL \
--id $(aws wafv2 list-web-acls --scope REGIONAL --query "WebACLs[?Name=='api-gateway-waf'].Id" --output text) \
--lock-token $(aws wafv2 get-web-acl --name api-gateway-waf --scope REGIONAL --id WEB_ACL_ID --query 'LockToken' --output text) \
--default-action '{"Allow":{}}' \
--visibility-config '{
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "api-gateway-waf"
}' \
--rules '[
{
"Name": "RateLimitPerIP",
"Priority": 0,
"Statement": {
"RateBasedStatement": {
"Limit": 2000,
"AggregateKeyType": "IP"
}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RateLimitPerIP"
}
},
{
"Name": "RateLimitLoginEndpoint",
"Priority": 5,
"Statement": {
"RateBasedStatement": {
"Limit": 100,
"AggregateKeyType": "IP",
"ScopeDownStatement": {
"ByteMatchStatement": {
"FieldToMatch": {"UriPath": {}},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/api/auth/login",
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}]
}
}
}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RateLimitLogin"
}
}
]'
Add AWS WAF Bot Control to detect and manage automated traffic.
# Add Bot Control managed rule group
# (Add to the rules array when updating the Web ACL)
{
"Name": "AWSManagedRulesBotControlRuleSet",
"Priority": 6,
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesBotControlRuleSet",
"ManagedRuleGroupConfigs": [{
"AWSManagedRulesBotControlRuleSet": {
"InspectionLevel": "COMMON"
}
}],
"ExcludedRules": [
{"Name": "CategoryHttpLibrary"},
{"Name": "SignalNonBrowserUserAgent"}
]
}
},
"OverrideAction": {"None": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "BotControl"
}
}
Build custom WAF rules for API-specific security requirements.
# Block requests without required API key header
{
"Name": "RequireAPIKey",
"Priority": 7,
"Statement": {
"NotStatement": {
"Statement": {
"ByteMatchStatement": {
"FieldToMatch": {
"SingleHeader": {"Name": "x-api-key"}
},
"PositionalConstraint": "EXACTLY",
"SearchString": "",
"TextTransformations": [{"Priority": 0, "Type": "NONE"}]
}
}
}
},
"Action": {"Block": {"CustomResponse": {"ResponseCode": 403}}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RequireAPIKey"
}
}
# Geo-restrict to allowed countries
{
"Name": "GeoRestriction",
"Priority": 8,
"Statement": {
"NotStatement": {
"Statement": {
"GeoMatchStatement": {
"CountryCodes": ["US", "CA", "GB", "DE", "FR", "AU"]
}
}
}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "GeoRestriction"
}
}
# Block oversized request bodies (prevent payload attacks)
{
"Name": "MaxBodySize",
"Priority": 9,
"Statement": {
"SizeConstraintStatement": {
"FieldToMatch": {"Body": {"OversizeHandling": "MATCH"}},
"ComparisonOperator": "GT",
"Size": 10240,
"TextTransformations": [{"Priority": 0, "Type": "NONE"}]
}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "MaxBodySize"
}
}
Attach the Web ACL to the API Gateway stage and configure comprehensive logging.
# Associate Web ACL with API Gateway
aws wafv2 associate-web-acl \
--web-acl-arn $WEB_ACL_ARN \
--resource-arn arn:aws:apigateway:us-east-1::/restapis/API_ID/stages/prod
# Enable WAF logging to S3 via Kinesis Firehose
aws wafv2 put-logging-configuration \
--logging-configuration '{
"ResourceArn": "'$WEB_ACL_ARN'",
"LogDestinationConfigs": [
"arn:aws:firehose:us-east-1:ACCOUNT:deliverystream/aws-waf-logs-api-gateway"
],
"RedactedFields": [
{"SingleHeader": {"Name": "authorization"}},
{"SingleHeader": {"Name": "cookie"}}
]
}'
# Verify association
aws wafv2 get-web-acl-for-resource \
--resource-arn arn:aws:apigateway:us-east-1::/restapis/API_ID/stages/prod
Monitor WAF effectiveness and tune rules to reduce false positives.
# Get WAF metrics from CloudWatch
aws cloudwatch get-metric-statistics \
--namespace AWS/WAFV2 \
--metric-name BlockedRequests \
--dimensions Name=WebACL,Value=api-gateway-waf Name=Rule,Value=ALL \
--start-time 2026-02-22T00:00:00Z \
--end-time 2026-02-23T00:00:00Z \
--period 3600 \
--statistics Sum
# Get sampled requests for a specific rule
aws wafv2 get-sampled-requests \
--web-acl-arn $WEB_ACL_ARN \
--rule-metric-name RateLimitPerIP \
--scope REGIONAL \
--time-window '{"StartTime":"2026-02-22T00:00:00Z","EndTime":"2026-02-23T00:00:00Z"}' \
--max-items 50
# Check rate-limited IPs
aws wafv2 get-rate-based-statement-managed-keys \
--web-acl-name api-gateway-waf \
--scope REGIONAL \
--web-acl-id WEB_ACL_ID \
--rule-name RateLimitPerIP
# Create CloudWatch alarm for high block rate
aws cloudwatch put-metric-alarm \
--alarm-name waf-high-block-rate \
--namespace AWS/WAFV2 \
--metric-name BlockedRequests \
--dimensions Name=WebACL,Value=api-gateway-waf Name=Rule,Value=ALL \
--statistic Sum --period 300 --threshold 1000 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-east-1:ACCOUNT:security-alerts
| Term | Definition | |------|------------| | Web ACL | AWS WAF access control list that defines the collection of rules and their actions (allow, block, count) applied to associated resources | | Managed Rule Group | Pre-configured set of WAF rules maintained by AWS or third-party vendors for common attack patterns like OWASP Top 10 | | Rate-Based Rule | WAF rule that tracks request rates per IP address and blocks traffic exceeding a defined threshold within a 5-minute window | | Bot Control | AWS WAF managed rule group that identifies and manages automated traffic including scrapers, crawlers, and attack bots | | IP Reputation List | AWS-maintained list of IP addresses associated with malicious activity including botnets, scanners, and known attackers | | Custom Response | WAF capability to return specific HTTP status codes and custom response bodies when blocking requests |
Context: A public REST API experiences thousands of authentication attempts per hour from automated bots attempting credential stuffing against the /api/auth/login endpoint.
Approach:
Pitfalls: Rate limiting by IP can block legitimate users behind shared NAT gateways or corporate proxies. Consider using API key or authenticated session-based rate limiting for more granular control. Bot Control rules in COMMON inspection level may block legitimate API clients; start in Count mode and review before switching to Block.
AWS WAF API Gateway Security Report
======================================
Web ACL: api-gateway-waf
Associated Resource: API Gateway - production-api (prod stage)
Report Period: 2026-02-16 to 2026-02-23
TRAFFIC SUMMARY:
Total requests: 2,450,000
Allowed requests: 2,380,000 (97.1%)
Blocked requests: 70,000 (2.9%)
BLOCKS BY RULE:
RateLimitPerIP: 28,000 (40%)
AWSManagedRulesCommonRuleSet: 18,000 (25.7%)
BotControl: 12,000 (17.1%)
SQLiRuleSet: 5,000 (7.1%)
IPReputationList: 4,000 (5.7%)
RateLimitLogin: 2,000 (2.9%)
GeoRestriction: 1,000 (1.4%)
TOP BLOCKED IPs:
185.x.x.x: 8,400 requests (rate limited)
45.x.x.x: 5,200 requests (bot detected)
198.x.x.x: 3,100 requests (SQLi attempts)
ATTACK TYPES BLOCKED:
Credential stuffing (login endpoint): 2,000
SQL injection attempts: 5,000
Cross-site scripting: 3,200
Known bad bot traffic: 12,000
Rate limit violations: 28,000
WAF RULE HEALTH:
Rules in Block mode: 8 / 10
Rules in Count mode: 2 / 10 (under evaluation)
False positive rate: < 0.1%
development
拋棄式 HTML mockup 比稿:產出 2 到 3 個設計立場不同的變體(密度 / 版式 / 強調軸,不是換色),各附取捨說明,最後給有立場的對比結論。適用:「畫個草圖」「比較 A 版 B 版」「先看方向再做」「給我看幾種做法」。要 production 元件或設計已定案時不適用。
tools
需求不明時的意圖萃取訪談:一次一題、每題附上自己的猜測、聽出「真正想要 vs 覺得應該要」,直到能預測使用者反應(約 95% 信心)才動工。適用:需求缺少對象 / 動機 / 成功標準 / 約束,或使用者點名「訪談我」「先確認一下」「我們確定嗎」。明確自足的指示、純資訊查詢、機械性操作不適用。
development
對非平凡決策啟動新鮮 context 對抗審查(找碴不背書),在修正還便宜的時候抓出錯誤方向。適用:高風險改動(production、資安敏感邏輯、不可逆操作)、不熟的程式碼、要宣稱「這樣是安全的 / 可行的」之前。機械性操作與一行修改不適用。
testing
Reference for writing and editing agent skills well — the vocabulary and principles that make a skill predictable. Consult when authoring, reviewing, or pruning a SKILL.md.