CKV_AWS_24, CKV_AWS_25 and CKV_AWS_260 silently skip a security group when FromPort resolves to a non-integer
Describe the issue
AbsSecurityGroupUnrestrictedIngress.range() calls int(rule['FromPort'])
without guarding it. When FromPort is a Ref to a parameter whose resolved
value is not an integer, the call raises ValueError, the framework logs it and
moves on, and the check produces no result at all. It is not reported as failed,
passed or skipped, so the scan is green on a rule nobody checked.
CKV_AWS_24 (port 22), CKV_AWS_25 (port 3389) and CKV_AWS_260 (port 80) all
inherit range(), so one unparsable port disables all three on that resource.
evaluate-variables: true makes this easy to hit, because a parameter with
Default: '' is substituted into the property. An empty string is a normal way
to spell an optional parameter in CloudFormation.
Examples
.checkov.yaml:
evaluate-variables: truerepro.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
IngressPort:
Type: String
Default: ''
Resources:
Group:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'repro'
VpcId: 'vpc-00000000'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !Ref IngressPort
ToPort: !Ref IngressPort
CidrIp: '0.0.0.0/0'checkov --framework cloudformation --config-file .checkov.yaml -f repro.yaml:
[ERROR] Failed to run check CKV_AWS_24 on /repro.yaml:AWS::EC2::SecurityGroup.Group
Traceback (most recent call last):
File ".../checkov/common/checks/base_check.py", line 68, in run
check_result["result"] = self.scan_entity_conf(entity_configuration, entity_type)
File ".../checkov/cloudformation/checks/resource/base_resource_check.py", line 33, in scan_entity_conf
return self.scan_resource_conf(conf)
File ".../checkov/cloudformation/checks/resource/aws/AbsSecurityGroupUnrestrictedIngress.py", line 39, in scan_resource_conf
if self.range(rule):
File ".../checkov/cloudformation/checks/resource/aws/AbsSecurityGroupUnrestrictedIngress.py", line 50, in range
if int(rule['FromPort']) <= int(self.port) <= int(rule['ToPort']):
ValueError: invalid literal for int() with base 10: ''Same traceback for CKV_AWS_25 and CKV_AWS_260. Results:
Passed checks: 0, Failed checks: 1, Skipped checks: 0The one failure is CKV_AWS_23. The three port checks are absent from every count.
Version
checkov 3.3.16, python 3.13, alpine.
Additional context
scan_resource_conf already gates on the types of FromPort and ToPort
matching, but str and str passes that gate for any pair of strings. A guard
in range() that returns CheckResult.UNKNOWN (or has range() report that it
could not decide) would keep the resource in the report instead of dropping it.
Failing loudly would also be an improvement over the current behaviour, since
today the only signal is a log line on stderr that a CI job is likely to
discard.
A resource-level suppression is a workaround, and it at least makes the gap
visible: # checkov:skip=CKV_AWS_24:reason on the resource turns the three
missing results into three reported as skipped.
Source: bridgecrewio/checkov