Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · WAF

WAF.3: WAF Classic regional rule groups should have a rule

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub WAF.3 check?

WAF.3 checks AWS WAF Classic Regional rule groups (`AWS::WAFRegional::RuleGroup`, the ALB/API Gateway tier). It reports FAILED when a rule group contains zero rules — `list-activated-rules-in-rule-group` returns an empty array, so the group is inert no matter how it's named or where it's attached.

Why does WAF.3 matter?

An empty rule group is a no-op: it can be wired into a web ACL, show up in the console with a confident name like `block-sqli`, and inspect nothing, so every request flows straight through to the web ACL's default action. The danger is that everyone downstream — architecture diagrams, audits — assumes the named protection exists when it doesn't.

How do I fix WAF.3?

  1. Confirm intent for each empty group: was it scaffolded and never finished, or is it dead scaffolding?
  2. Either populate the group with real rules, or detach it from any web ACL and delete it.
  3. Use the WAF Classic change-token workflow to apply the change.
  4. Tag the survivors so the next audit is shorter and the empty-group pattern doesn't recur.

Remediation script · bash

# Attach the AWS Managed Rules common baseline to an empty web ACL, in Count mode.
# update-web-acl REPLACES the entire Rules array, so supply the full desired set and the current LockToken.
aws wafv2 update-web-acl \
  --scope REGIONAL --name public-alb-waf --id a1b2c3d4-0000-1111-2222-3333 \
  --lock-token e4f5g6h7 --default-action Allow={} \
  --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=public-alb-waf \
  --rules '[{"Name":"AWS-CommonRuleSet","Priority":0,"Statement":{"ManagedRuleGroupStatement":{"VendorName":"AWS","Name":"AWSManagedRulesCommonRuleSet"}},"OverrideAction":{"Count":{}},"VisibilityConfig":{"SampledRequestsEnabled":true,"CloudWatchMetricsEnabled":true,"MetricName":"AWS-CommonRuleSet"}}]'

# Associate a baseline web ACL with an unprotected API Gateway stage (the resource ARN is the stage, not the API).
aws wafv2 associate-web-acl \
  --web-acl-arn arn:aws:wafv2:us-east-1:111122223333:regional/webacl/prod-api-baseline/1a2b3c4d \
  --resource-arn arn:aws:apigateway:us-east-1::/restapis/a1b2c3d4e5/stages/prod

# Protect a Network Firewall from accidental deletion.
aws network-firewall update-firewall-delete-protection \
  --firewall-name prod-egress-inspection --delete-protection

Full walkthrough (console steps, edge cases and verification) in the lesson Protect APIs and edge with WAF.

Part of the learning path Lock down access
  • WAF.1 WAF Classic global web ACL logging
  • WAF.2 WAF Classic regional rules should have a condition
  • WAF.4 WAF Classic regional web ACLs should have a rule
  • WAF.6 WAF Classic global rules should have a condition
  • WAF.7 WAF Classic global rule groups should have a rule
  • WAF.8 WAF Classic global web ACLs should have a rule
  • WAF.10 WAFv2 web ACLs should have a rule or rule group
  • WAF.11 WAFv2 web ACL logging should be enabled