Repository: liamg/tfsec (go)

Issue:
IPv6 open rules
Tfsec appears to not warn about IPv6 open security groups and NACL rules.

Example:
```hcl
resource "aws_security_group_rule" "example" {
  type = "ingress"
  from_port = 443
  to_port = 443
  protocol = "tcp"
  cidr_blocks = ["0.0.0.0/0"] # => Detected properly
  ipv6_cidr_blocks = ["::/0"] # => Not detected
  security_group_id = "sg-123456"
}
```


Pull request description:
Add ipv6 support for aws security group rules
Closes #138 

Patch:
diff --git a/internal/app/tfsec/checks/aws_open_security_group_rules.go b/internal/app/tfsec/checks/aws_open_security_group_rules.go
index 7632423ec..824fa998c 100644
--- a/internal/app/tfsec/checks/aws_open_security_group_rules.go
+++ b/internal/app/tfsec/checks/aws_open_security_group_rules.go
@@ -53,6 +53,27 @@ func init() {
 
 			}
 
+			if ipv6CidrBlocksAttr := block.GetAttribute("ipv6_cidr_blocks"); ipv6CidrBlocksAttr != nil {
+
+				if ipv6CidrBlocksAttr.Value().IsNull() || ipv6CidrBlocksAttr.Value().LengthInt() == 0 {
+					return nil
+				}
+
+				for _, cidr := range ipv6CidrBlocksAttr.Value().AsValueSlice() {
+					if strings.HasSuffix(cidr.AsString(), "/0") {
+						return []scanner.Result{
+							check.NewResultWithValueAnnotation(
+								fmt.Sprintf("Resource '%s' defines a fully open egress security group rule.", block.Name()),
+								ipv6CidrBlocksAttr.Range(),
+								ipv6CidrBlocksAttr,
+								scanner.SeverityWarning,
+							),
+						}
+					}
+				}
+
+			}
+
 			return nil
 		},
 	})
@@ -93,6 +114,27 @@ func init() {
 
 			}
 
+			if ipv6CidrBlocksAttr := block.GetAttribute("ipv6_cidr_blocks"); ipv6CidrBlocksAttr != nil {
+
+				if ipv6CidrBlocksAttr.Value().IsNull() || ipv6CidrBlocksAttr.Value().LengthInt() == 0 {
+					return nil
+				}
+
+				for _, cidr := range ipv6CidrBlocksAttr.Value().AsValueSlice() {
+					if strings.HasSuffix(cidr.AsString(), "/0") {
+						return []scanner.Result{
+							check.NewResultWithValueAnnotation(
+								fmt.Sprintf("Resource '%s' defines a fully open egress security group rule.", block.Name()),
+								ipv6CidrBlocksAttr.Range(),
+								ipv6CidrBlocksAttr,
+								scanner.SeverityWarning,
+							),
+						}
+					}
+				}
+
+			}
+
 			return nil
 		},
 	})
diff --git a/internal/app/tfsec/checks/aws_open_security_groups.go b/internal/app/tfsec/checks/aws_open_security_groups.go
index f023c1f99..a3126f0d6 100644
--- a/internal/app/tfsec/checks/aws_open_security_groups.go
+++ b/internal/app/tfsec/checks/aws_open_security_groups.go
@@ -31,6 +31,24 @@ func init() {
 						return nil
 					}
 
+					for _, cidr := range cidrBlocksAttr.Value().AsValueSlice() {
+						if strings.HasSuffix(cidr.AsString(), "/0") {
+							results = append(results,
+								check.NewResult(
+									fmt.Sprintf("Resource '%s' defines a fully open ingress security group.", block.Name()),
+									cidrBlocksAttr.Range(),
+									scanner.SeverityWarning,
+								),
+							)
+						}
+					}
+				}
+				if cidrBlocksAttr := directionBlock.GetAttribute("ipv6_cidr_blocks"); cidrBlocksAttr != nil {
+
+					if cidrBlocksAttr.Value().IsNull() || cidrBlocksAttr.Value().LengthInt() == 0 {
+						return nil
+					}
+
 					for _, cidr := range cidrBlocksAttr.Value().AsValueSlice() {
 						if strings.HasSuffix(cidr.AsString(), "/0") {
 							results = append(results,
@@ -64,6 +82,25 @@ func init() {
 						return nil
 					}
 
+					for _, cidr := range cidrBlocksAttr.Value().AsValueSlice() {
+						if strings.HasSuffix(cidr.AsString(), "/0") {
+							results = append(results,
+								check.NewResultWithValueAnnotation(
+									fmt.Sprintf("Resource '%s' defines a fully open egress security group.", block.Name()),
+									cidrBlocksAttr.Range(),
+									cidrBlocksAttr,
+									scanner.SeverityWarning,
+								),
+							)
+						}
+					}
+				}
+				if cidrBlocksAttr := directionBlock.GetAttribute("ipv6_cidr_blocks"); cidrBlocksAttr != nil {
+
+					if cidrBlocksAttr.Value().IsNull() || cidrBlocksAttr.Value().LengthInt() == 0 {
+						return nil
+					}
+
 					for _, cidr := range cidrBlocksAttr.Value().AsValueSlice() {
 						if strings.HasSuffix(cidr.AsString(), "/0") {
 							results = append(results,


Test patch:
diff --git a/internal/app/tfsec/aws_open_security_group_rule_test.go b/internal/app/tfsec/aws_open_security_group_rule_test.go
index 5d1df2e77..1f49be291 100644
--- a/internal/app/tfsec/aws_open_security_group_rule_test.go
+++ b/internal/app/tfsec/aws_open_security_group_rule_test.go
@@ -73,6 +73,15 @@ variable "blocks" {
 `,
 			mustIncludeResultCode: checks.AWSOpenIngressSecurityGroupRule,
 		},
+		{
+			name: "check aws_security_group_rule ingress on ::/0",
+			source: `
+resource "aws_security_group_rule" "my-rule" {
+	type = "ingress"
+	ipv6_cidr_blocks = ["::/0"]
+}`,
+			mustIncludeResultCode: checks.AWSOpenIngressSecurityGroupRule,
+		},
 	}
 
 	for _, test := range tests {
diff --git a/internal/app/tfsec/aws_open_security_group_test.go b/internal/app/tfsec/aws_open_security_group_test.go
index 732f1021d..ff12cb0e0 100644
--- a/internal/app/tfsec/aws_open_security_group_test.go
+++ b/internal/app/tfsec/aws_open_security_group_test.go
@@ -143,6 +143,16 @@ variable "cidr_2" {
 `,
 			mustIncludeResultCode: checks.AWSOpenEgressSecurityGroupInlineRule,
 		},
+		{
+			name: "check aws_security_group ingress on ::/0",
+			source: `
+		resource "aws_security_group" "my-group" {
+			ingress {
+				ipv6_cidr_blocks = ["0.0.0.0/0"]
+			}
+		}`,
+			mustIncludeResultCode: checks.AWSOpenIngressSecurityGroupInlineRule,
+		},
 	}
 
 	for _, test := range tests {