Skip to content

fix(core): suppress false-positive E9002 validation warning for ICMP security group rules - #38395

Open
fifthist wants to merge 1 commit into
aws:mainfrom
fifthist:fix/icmp-e9002-false-warning
Open

fix(core): suppress false-positive E9002 validation warning for ICMP security group rules#38395
fifthist wants to merge 1 commit into
aws:mainfrom
fifthist:fix/icmp-e9002-false-warning

Conversation

@fifthist

@fifthist fifthist commented Jul 24, 2026

Copy link
Copy Markdown

Closes #38389.

Reason for this change

Since the @aws/cloudformation-validate engine was wired into synth-time validation, cdk synth emits a spurious warning for perfectly valid ICMP security group rules:

WARNING SecurityGroupIngress: FromPort 8 is greater than ToPort -1 (CloudFormation Validate)
   .../EmcEc21Sg/Resource (EmcEc21Sg6A5E663D) aws-cdk-lib.aws_ec2.CfnSecurityGroup
   Suggested fix: Set FromPort to a value less than or equal to ToPort
   Acknowledge with 'CloudFormation-Validate::E9002'

The engine's E9002 rule is a generic "FromPort must be <= ToPort" port-range check. It does not account for the fact that for ICMP/ICMPv6 rules, FromPort and ToPort are not a port range — they encode the ICMP type and code, where -1 means "all". So a completely ordinary rule like:

sg.addIngressRule(Peer.anyIpv4(), Port.icmpPing());

renders the valid CloudFormation below and yet trips E9002:

SecurityGroupIngress:
  - CidrIp: 0.0.0.0/0
    FromPort: 8       # ICMP type 8 (echo request)
    IpProtocol: icmp
    ToPort: -1        # ICMP code -1 (all codes)

There is no consumer-side workaround short of acknowledging/suppressing the rule globally, which is undesirable (see below).

Description of changes

The finding is a false positive that originates in the upstream engine's rule, so the fix lives where CDK already curates engine output: the CloudFormationValidatePlugin.

Instead of suppressing E9002 globally, the plugin now correlates each E9002 finding back to the specific security group rule that produced it and drops the finding only when that rule uses an ICMP protocol. The engine emits one E9002 diagnostic per offending rule, and its message names the exact ports ("FromPort 8 is greater than ToPort -1"), so we match those ports against the rule declared in the template and check its IpProtocol. ICMP is recognized whether given by name (icmp/icmpv6) or IANA number (1/58). The check covers inline SecurityGroupIngress/SecurityGroupEgress arrays as well as the standalone AWS::EC2::SecurityGroupIngress/Egress resources.

The template is parsed lazily (once per stack, only when an E9002 finding is actually present), so there is no cost for the common case.

A code comment links back to this issue so the workaround can be removed once the engine understands ICMP rules.

Why not simply add E9002 to the IGNORE_RULES list?

That was the originally suggested fix, but adding E9002 to IGNORE_RULES (or excluding it per-service via the engine's exclude.services) suppresses the rule for every resource, which would silently hide genuine misconfigurations that E9002 is meant to catch. E9002 is a real, useful rule for TCP/UDP — it only misfires on ICMP.

Concretely, all of the following are legitimate E9002 errors that a blanket ignore would swallow:

# A TCP range typo — 443 down to 80 is invalid and would be rejected by CloudFormation.
- IpProtocol: tcp
  FromPort: 443
  ToPort: 80
# A UDP range that is backwards.
- IpProtocol: udp
  FromPort: 8080
  ToPort: 8000

The targeted approach keeps those errors visible. This is verified explicitly by the tests, including the case where a single security group mixes an ICMP rule and a bad TCP range — only the ICMP finding is dropped:

Rule on the security group E9002 before E9002 after this change
icmp, FromPort 8, ToPort -1 (Port.icmpPing()) ⚠️ reported (false positive) ✅ suppressed
icmpv6, FromPort 128, ToPort -1 ⚠️ reported (false positive) ✅ suppressed
protocol 1 (numeric ICMP), FromPort 8, ToPort -1 ⚠️ reported (false positive) ✅ suppressed
tcp, FromPort 443, ToPort 80 (real typo) ⚠️ reported ⚠️ still reported

A per-service exclude (AWS::EC2 / AWS::EC2::SecurityGroup) has the same problem: security groups carry both ICMP and TCP/UDP rules, so scoping the suppression to the service would still hide the TCP typo above. Only correlating down to the individual rule's protocol preserves the rule's value while removing the false positive.

Describe any new or updated permissions being added

None.

Description of how you validated changes

Added unit tests in cloudformation-validate-plugin.test.ts:

  • No E9002 for ICMP rules — parametrized over icmp, icmpv6, and the numeric protocol 1.
  • E9002 is still reported for a genuine TCP range error (FromPort: 443, ToPort: 80), guarding against over-suppression.
  • Mixed security group — a resource containing both an ICMP rule and a bad TCP range yields exactly one E9002 finding (the TCP one), proving the suppression is per-rule, not per-resource.

I also reproduced the original false positive and validated the suppression logic directly against the pinned engine version (@aws/cloudformation-validate@1.5.1-beta) for every case in the table above.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

…security group rules

The `@aws/cloudformation-validate` engine's `E9002` rule ("FromPort is
greater than ToPort") does not account for ICMP/ICMPv6 security group
rules, where `FromPort`/`ToPort` encode the ICMP type/code (with `-1`
meaning "all") rather than an ordered port range. As a result, common
rules such as `Port.icmpPing()` (which renders `FromPort: 8, ToPort: -1`)
emit a spurious warning on `cdk synth`.

Rather than suppressing `E9002` wholesale (which would also hide genuine
TCP/UDP range misconfigurations), correlate each `E9002` finding back to
the specific offending security group rule and drop it only when that
rule uses an ICMP protocol. Real range errors — including on the same
resource — continue to be reported.

Closes aws#38389.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fifthist
fifthist requested a review from a team as a code owner July 24, 2026 02:08
@github-actions github-actions Bot added bug This issue is a bug. effort/small Small work item – less than a day of effort p2 beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK labels Jul 24, 2026
@aws-cdk-automation
aws-cdk-automation requested a review from a team July 24, 2026 02:08

@aws-cdk-automation aws-cdk-automation left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pull request linter fails with the following errors:

❌ Fixes must contain a change to an integration test file and the resulting snapshot.

If you believe this pull request should receive an exemption, please comment and provide a justification. A comment requesting an exemption should contain the text Exemption Request. Additionally, if clarification is needed, add Clarification Request to a comment.

✅ A exemption request has been requested. Please wait for a maintainer's review.

@fifthist

Copy link
Copy Markdown
Author

Exemption Request

This change does not lend itself to an integration test, and I'd like to request an exemption on that basis.

The fix only filters a synth-time validation diagnostic — it makes the CloudFormationValidatePlugin skip the ICMP false-positive E9002 finding (a single continue in the diagnostics loop). It does not touch resource or template generation in any way, so the synthesized .template.json is byte-for-byte identical with and without this change. An integration test's value is its template snapshot, and here that snapshot would show no difference, so it cannot capture or protect the behavior being fixed.

The behavior is instead covered by unit tests in cloudformation-validate-plugin.test.ts, which exercise the actual @aws/cloudformation-validate engine:

  • no E9002 reported for ICMP rules (parametrized over icmp, icmpv6, and the numeric protocol 1);
  • E9002 still reported for a genuine TCP range error (FromPort: 443, ToPort: 80), guarding against over-suppression;
  • a mixed security group (ICMP rule + bad TCP range) yields exactly one E9002 finding — the TCP one — proving the suppression is per-rule, not per-resource.

There is also no existing integration-test surface for the core validation plugin (packages/aws-cdk-lib/core has no integ.* tests for validation), which is consistent with this being synth-time-only infrastructure rather than resource generation.

Happy to add anything else that would help review.

@aws-cdk-automation aws-cdk-automation added the pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback. label Jul 24, 2026
@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK bug This issue is a bug. effort/small Small work item – less than a day of effort p2 pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core: CloudFormation-Validate::E9002

2 participants