From 7bf04753724ce524a01fa7c307e2b12334109612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Rodr=C3=ADguez?= Date: Sun, 14 Jun 2026 14:18:24 -0600 Subject: [PATCH] Add firewall IPv6 service tag evidence gates --- skills/network/firewall-review/SKILL.md | 80 ++++++++++++++++++- ...ipv6-disabled-service-tag-constrained.json | 49 ++++++++++++ .../ipv6-any-service-tag-no-expansion.json | 50 ++++++++++++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 skills/network/firewall-review/tests/benign/ipv6-disabled-service-tag-constrained.json create mode 100644 skills/network/firewall-review/tests/vulnerable/ipv6-any-service-tag-no-expansion.json diff --git a/skills/network/firewall-review/SKILL.md b/skills/network/firewall-review/SKILL.md index 25f8e588..727fec12 100644 --- a/skills/network/firewall-review/SKILL.md +++ b/skills/network/firewall-review/SKILL.md @@ -13,7 +13,7 @@ phase: [operate] frameworks: [CIS-Controls-v8, NIST-SP-800-41-Rev1] difficulty: intermediate time_estimate: "30-60min" -version: "1.0.0" +version: "1.0.1" author: unitoneai license: MIT allowed-tools: Read, Grep, Glob @@ -69,6 +69,11 @@ Use Glob and Grep to locate firewall configuration files, ACL definitions, and n **/firewall-rule* **/*nsg* **/*nacl* +**/*service-tag* +**/*prefix-list* +**/*ip-ranges* +**/*cdn* +**/*waf* # Infrastructure-as-Code definitions **/*.tf # Terraform (aws_security_group, google_compute_firewall, azurerm_network_security_group) @@ -80,6 +85,8 @@ Record all discovered files. Categorize each by: - **Platform:** iptables, nftables, pf, cloud security groups, Kubernetes NetworkPolicy, vendor-specific (Palo Alto, Fortinet, Cisco ASA). - **Direction:** Perimeter (north-south) vs. internal (east-west). - **Scope:** Server, endpoint, network segment. +- **Address family:** IPv4, IPv6, or dual-stack. +- **Abstraction type:** Literal CIDR, provider service tag, managed prefix list, FQDN rule, CDN/provider range, Kubernetes selector, or vendor object. --- @@ -254,6 +261,63 @@ Egress filtering prevents compromised internal hosts from establishing unrestric --- +#### 2.8 Dual-Stack, Service-Tag, and Provider-Range Effective Exposure + +Modern firewall policy often hides the real reachable surface behind IPv6 defaults, provider-managed service tags, shared prefix lists, CDN/WAF ranges, FQDN rules, Kubernetes policy layers, or host firewalls. Review the effective path before scoring a rule as safe or unsafe. + +**IPv6 parity checks:** + +- For every public IPv4 allow rule, verify whether an equivalent IPv6 path exists (`::/0`, public IPv6 CIDRs, IPv6 security group rules, `ip6tables`, cloud load balancer IPv6 listeners, Kubernetes dual-stack services). +- If a finding is marked IPv4-only, require evidence that IPv6 is disabled or equivalently restricted at every relevant enforcement layer: edge/WAF, load balancer, security group or NSG, subnet ACL, host firewall, and Kubernetes NetworkPolicy/CNI where applicable. +- Treat `0.0.0.0/0` closed but `::/0` open as equivalent public exposure, not as a lower-risk exception. +- Verify split enforcement: security groups, NACLs, host firewalls, WAF/CDN controls, Kubernetes NetworkPolicy, service mesh policy, and egress gateways must agree across IPv4 and IPv6. + +**Service tag / prefix list / provider range checks:** + +- Expand cloud service tags, managed prefix lists, CDN/WAF provider ranges, and vendor address objects at review time. Record the expansion source, retrieval timestamp, region/service filter, and resulting CIDR families. +- Do not flag a broad provider tag automatically when compensating controls prove the resource is still constrained, such as private endpoint, resource policy, identity condition, storage/firewall data-plane restriction, WAF origin validation, or mTLS. +- Flag broad tags such as `Internet`, `AzureCloud`, all-provider ranges, shared prefix lists, or CDN source ranges when there is no resource-level control proving the destination cannot be widened outside the intended service or region. +- Require drift controls for provider-managed ranges: owner, update automation, last successful refresh, failure alerting, and change review for manually copied CIDR lists. + +**Detection methods using allowed tools:** + +``` +# IPv6 and dual-stack exposure +Grep: "::/0|ipv6_cidr_blocks|destination_ipv6|source_ipv6|ip6tables|ip -6|dual-stack|ipFamilyPolicy|ipFamilies" in **/*.{tf,yaml,yml,json,conf} + +# Provider-managed abstractions and range drift +Grep: "service_tag|serviceTags|AzureCloud|Internet|prefix_list|managed_prefix|aws_ip_ranges|goog.json|cloud.json|cdn|waf|FQDN|fqdn_tags" in **/*.{tf,yaml,yml,json,conf} + +# Split enforcement layers +Grep: "network_acl|security_group|azurerm_network_security_rule|google_compute_firewall|NetworkPolicy|CiliumNetworkPolicy|AuthorizationPolicy|ingressGateway|egressGateway" in **/*.{tf,yaml,yml,json} +``` + +**Effective exposure evidence table:** + +| Evidence Item | Required Evidence | Risk If Missing | +|---|---|---| +| IPv6 status | IPv6 disabled proof or equivalent IPv6 rule review across all layers | Public IPv6 bypass of IPv4 controls | +| Expanded abstraction | Service tag, prefix list, CDN/WAF, or vendor object expansion with timestamp/source | Friendly name hides broad provider or Internet exposure | +| Region/service scope | Region, service, account/project, and environment filter | Rule includes services or regions outside the intended boundary | +| Compensating controls | Private endpoint, resource policy, identity condition, origin validation, WAF rule, or mTLS evidence | Broad network allow becomes effective data-plane access | +| Drift management | Owner, automation, last refresh, failed-refresh alerting, and change review | Stale provider ranges silently block or expose traffic | +| Split enforcement | SG/NACL/host/WAF/Kubernetes/service-mesh parity for IPv4 and IPv6 | One layer allows what another layer appears to deny | + +**What constitutes a finding:** + +| Condition | Severity | +|---|---| +| FW-DUAL-01: Public IPv6 allow (`::/0` or public IPv6 CIDR) exists where IPv4 is restricted | Critical for inbound, High for outbound | +| FW-DUAL-02: IPv6 is assumed absent without evidence at edge, load balancer, cloud firewall, host, and Kubernetes layers | High | +| FW-TAG-01: Service tag, prefix list, CDN/WAF range, or vendor object is accepted without expansion evidence | High | +| FW-TAG-02: Broad provider tag or all-provider range lacks private endpoint, identity, resource-policy, or origin-validation controls | High | +| FW-DRIFT-01: Provider/CDN range allowlist is manually copied with no owner, refresh cadence, or failed-refresh alert | Medium | +| FW-SPLIT-01: Security group, NACL, host firewall, WAF/CDN, Kubernetes, or service mesh policy disagree across IPv4/IPv6 | High | + +**Benign boundary:** A broad managed tag or prefix list may be acceptable when expansion evidence is current and the destination is also constrained by resource-level controls. An IPv4-only rule may be acceptable when there is explicit evidence that IPv6 is disabled or equivalently denied across the effective path. + +--- + ### Step 3: Compile Assessment Report Produce the final report using the following structure. @@ -317,6 +381,11 @@ Produce the final report using the following structure. | SMTP (25) | Yes/No | | | HTTPS (443) | Yes/No | | +### Dual-Stack and Provider Abstraction Evidence +| Control | IPv4 Evidence | IPv6 Evidence | Expanded Object / Tag | Compensating Control | Status | +|---------|---------------|---------------|------------------------|----------------------|--------| +| | | | | | Pass/Fail/Not Evaluable | + ### Prioritized Remediation Plan 1. **[Critical]** 2. **[High]** @@ -361,6 +430,10 @@ Produce the final report using the following structure. 5. **Conflating network ACLs with security groups in cloud environments.** In AWS, NACLs are stateless and operate at the subnet level; security groups are stateful and operate at the instance level. Both must be audited. A permissive NACL can undermine restrictive security group rules for responses. +6. **Trusting friendly provider names without expansion.** A service tag, managed prefix list, CDN object, or FQDN rule is not automatically narrow. Expand it, record the source and timestamp, and verify resource-level controls before treating the rule as constrained. + +7. **Reviewing one enforcement layer as the effective path.** A restrictive security group does not prove exposure is blocked if IPv6, WAF/CDN, host firewall, Kubernetes NetworkPolicy, service mesh, or egress gateway policy disagrees. Record the layers that actually see the traffic. + --- ## Prompt Injection Safety Notice @@ -381,9 +454,14 @@ This skill processes firewall configurations that may contain user-supplied comm - NIST SP 800-41 Rev 1, Guidelines on Firewalls and Firewall Policy: https://csrc.nist.gov/publications/detail/sp/800-41/rev-1/final - NIST SP 800-41 Rev 1 (PDF): https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-41r1.pdf - CIS Benchmarks (platform-specific firewall hardening): https://www.cisecurity.org/cis-benchmarks +- AWS IP address ranges: https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html +- Azure service tags: https://learn.microsoft.com/azure/virtual-network/service-tags-overview +- Google Cloud IP address ranges: https://cloud.google.com/vpc/docs/configure-private-google-access#ip-addr-defaults +- Kubernetes IPv4/IPv6 dual-stack: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ --- ## Changelog +- **1.0.1** -- Added IPv6 parity, service tag/prefix list expansion, provider range drift, and split enforcement evidence gates. - **1.0.0** -- Initial release. Full coverage of CIS Controls v8 (4.4, 4.5) and NIST SP 800-41 Rev 1 firewall audit methodology. diff --git a/skills/network/firewall-review/tests/benign/ipv6-disabled-service-tag-constrained.json b/skills/network/firewall-review/tests/benign/ipv6-disabled-service-tag-constrained.json new file mode 100644 index 00000000..eb33ba3c --- /dev/null +++ b/skills/network/firewall-review/tests/benign/ipv6-disabled-service-tag-constrained.json @@ -0,0 +1,49 @@ +{ + "case_id": "ipv6-disabled-service-tag-constrained", + "expected_decision": "pass", + "scenario": "Storage egress uses a provider service tag, but the effective path is private-endpoint and identity constrained, and IPv6 is disabled at every relevant layer.", + "firewall_rule": { + "direction": "egress", + "destination_abstraction": "Azure Storage service tag", + "ipv4_destination": "Storage.EastUS expanded ranges reviewed 2026-06-14", + "ipv6_destination": "none", + "ports": [ + "tcp/443" + ] + }, + "evidence": { + "service_tag_expansion": { + "source": "provider service tag export", + "retrieved_at": "2026-06-14T20:00:00Z", + "region_filter": "eastus", + "families_reviewed": [ + "ipv4", + "ipv6" + ] + }, + "ipv6_parity": { + "edge": "no IPv6 listener", + "load_balancer": "IPv6 disabled", + "network_security_group": "no destination IPv6 allow", + "host_firewall": "IPv6 default deny", + "kubernetes": "not applicable" + }, + "compensating_controls": [ + "private endpoint enabled", + "storage account public network access disabled", + "managed identity required", + "resource policy restricts approved subscription" + ], + "drift_management": { + "owner": "network-platform", + "refresh_cadence": "weekly", + "failed_refresh_alert": true + } + }, + "should_not_flag": [ + "FW-DUAL-01", + "FW-TAG-01", + "FW-TAG-02", + "FW-DRIFT-01" + ] +} diff --git a/skills/network/firewall-review/tests/vulnerable/ipv6-any-service-tag-no-expansion.json b/skills/network/firewall-review/tests/vulnerable/ipv6-any-service-tag-no-expansion.json new file mode 100644 index 00000000..d4187838 --- /dev/null +++ b/skills/network/firewall-review/tests/vulnerable/ipv6-any-service-tag-no-expansion.json @@ -0,0 +1,50 @@ +{ + "case_id": "ipv6-any-service-tag-no-expansion", + "expected_decision": "finding", + "scenario": "Inbound IPv4 is restricted, but IPv6 is open to the Internet and outbound provider tags are accepted without expansion or resource-level controls.", + "rules": [ + { + "name": "allow-https-ipv4-restricted", + "direction": "ingress", + "source": "203.0.113.0/24", + "destination": "web-tier", + "ports": [ + "tcp/443" + ] + }, + { + "name": "allow-https-ipv6-any", + "direction": "ingress", + "source": "::/0", + "destination": "web-tier", + "ports": [ + "tcp/443" + ] + }, + { + "name": "allow-provider-egress", + "direction": "egress", + "destination_abstraction": "AzureCloud", + "ports": [ + "tcp/443" + ], + "service_tag_expanded": false, + "resource_level_controls": [] + } + ], + "missing_evidence": [ + "IPv6 disabled proof at edge, load balancer, cloud firewall, and host", + "service tag expansion source and timestamp", + "region or service filter for provider tag", + "private endpoint, identity condition, resource policy, or origin validation", + "provider range refresh owner and failed-refresh alert" + ], + "expected_findings": [ + "FW-DUAL-01: public IPv6 allow exists while IPv4 is restricted", + "FW-DUAL-02: IPv6 absence is assumed without effective-path evidence", + "FW-TAG-01: provider service tag is accepted without expansion evidence", + "FW-TAG-02: broad provider tag lacks resource-level controls", + "FW-DRIFT-01: provider range allowlist has no owner or refresh evidence" + ], + "minimum_severity": "High" +}