Skip to main content
emnode
Compliance Medium severity

AWS Security Hub · WAF

WAF.7: WAF Classic global rule groups should have a rule

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub WAF.7 check?

WAF.7 checks AWS WAF Classic global rule groups (`AWS::WAF::RuleGroup`, the CloudFront-scoped tier managed through the `aws waf` API). It reports FAILED when a global rule group contains zero rules. It is the global twin of WAF.3, which checks the Regional `AWS::WAFRegional::RuleGroup`.

Why does WAF.7 matter?

An empty rule group is inert: when a web ACL invokes it there are no rules to evaluate, so every request passes through untouched: nothing allowed, blocked, or counted. The group still carries a name like `OWASP-Top-10` and tags implying coverage, so operators and auditors reasonably assume protection is in place at the CloudFront edge when none exists.

How do I fix WAF.7?

  1. Confirm the group is genuinely empty via the `aws waf` API (global resources always use the us-east-1 endpoint).
  2. Decide what the group should contain, if anything.
  3. Attach a real rule through the change-token workflow, or detach and delete the group.
  4. Verify the finding clears and prevent recurrence with a completion gate on new groups.

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.

Is WAF.7 a false positive?

It's easy to confuse the three API surfaces (`aws waf` (global), `aws waf-regional`, and `aws wafv2`) and querying the wrong one makes a global rule group look absent rather than empty.

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.3 WAF Classic regional rule groups should have a rule
  • WAF.4 WAF Classic regional web ACLs should have a rule
  • WAF.6 WAF Classic global rules should have a condition
  • 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