Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ CxPolicy[result] {
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_dms_replication_instance[%s].publicly_accessible should be set to false", [name]),
"keyActualValue": sprintf("aws_dms_replication_instance[%s].publicly_accessible is set to true", [name]),
"remediation": json.marshal({
"before": "true",
"after": "false",
}),
"remediationType": "replacement",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "8af4c38a-e1d2-405b-ac41-995db44b5536",
"queryName": "Beta - API Gateway V2 CORS Wildcard Origin Allowed",
"severity": "HIGH",
"category": "Insecure Configurations",
"descriptionText": "API Gateway V2 CORS configuration should not allow all origins ('*'). Wildcard origins allow any website to make cross-origin requests, enabling CSRF attacks against authenticated API endpoints.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apigatewayv2_api#allow_origins",
"platform": "Terraform",
"descriptionID": "c3d4e5f6",
"cloudProvider": "aws",
"cwe": "942",
"riskScore": "7.0",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package Cx

import data.generic.common as common_lib
import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_apigatewayv2_api[name]
cors := resource.cors_configuration
origins := cors.allow_origins
origins[_] == "*"
result := {
"documentId": input.document[i].id,
"resourceType": "aws_apigatewayv2_api",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_apigatewayv2_api[%s].cors_configuration.allow_origins", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_apigatewayv2_api[%s].cors_configuration.allow_origins should not contain wildcard '*'", [name]),
"keyActualValue": sprintf("aws_apigatewayv2_api[%s].cors_configuration.allow_origins contains wildcard '*'", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_apigatewayv2_api", name, "cors_configuration", "allow_origins"], []),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_apigatewayv2_api" "pass" {
name = "my-api"
protocol_type = "HTTP"

cors_configuration {
allow_origins = ["https://app.example.com"]
allow_methods = ["GET", "POST"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_apigatewayv2_api" "fail" {
name = "my-api"
protocol_type = "HTTP"

cors_configuration {
allow_origins = ["*"]
allow_methods = ["GET", "POST"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"queryName": "Beta - API Gateway V2 CORS Wildcard Origin Allowed",
"severity": "HIGH",
"line": 1,
"filename": "positive1.tf"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "c1c08f98-c7f0-4b28-8a6b-f9e99763c73a",
"queryName": "Beta - CloudFormation Stack Termination Protection Disabled",
"severity": "MEDIUM",
"category": "Insecure Configurations",
"descriptionText": "CloudFormation stacks should have termination protection enabled to prevent accidental or unauthorized stack deletion, which could cause irreversible infrastructure loss.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudformation_stack#termination_protection",
"platform": "Terraform",
"descriptionID": "b2c3d4e5",
"cloudProvider": "aws",
"cwe": "693",
"riskScore": "5.0",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package Cx

import data.generic.common as common_lib
import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_cloudformation_stack[name]
not common_lib.valid_key(resource, "termination_protection")
result := {
"documentId": input.document[i].id,
"resourceType": "aws_cloudformation_stack",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_cloudformation_stack[%s]", [name]),
"issueType": "MissingAttribute",
"keyExpectedValue": sprintf("aws_cloudformation_stack[%s].termination_protection should be true", [name]),
"keyActualValue": sprintf("aws_cloudformation_stack[%s].termination_protection is not defined", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_cloudformation_stack", name], []),
"remediation": "termination_protection = true",
"remediationType": "addition",
}
}

CxPolicy[result] {
resource := input.document[i].resource.aws_cloudformation_stack[name]
resource.termination_protection == false
result := {
"documentId": input.document[i].id,
"resourceType": "aws_cloudformation_stack",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_cloudformation_stack[%s].termination_protection", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_cloudformation_stack[%s].termination_protection should be true", [name]),
"keyActualValue": sprintf("aws_cloudformation_stack[%s].termination_protection is false", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_cloudformation_stack", name, "termination_protection"], []),
"remediation": json.marshal({
"before": "false",
"after": "true",
}),
"remediationType": "replacement",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "aws_cloudformation_stack" "pass" {
name = "my-stack"
template_body = file("template.yaml")
termination_protection = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "aws_cloudformation_stack" "fail" {
name = "my-stack"
template_body = file("template.yaml")
termination_protection = false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"queryName": "Beta - CloudFormation Stack Termination Protection Disabled",
"severity": "MEDIUM",
"line": 1,
"filename": "positive1.tf"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "ff2128f0-7084-4fec-81a6-dbd95b19a7ab",
"queryName": "Beta - Cognito User Pool Advanced Security Disabled",
"severity": "MEDIUM",
"category": "Access Control",
"descriptionText": "Amazon Cognito User Pools should enable advanced security features (AUDIT or ENFORCED mode) to detect and act on compromised credentials, anomalous sign-in attempts, and account takeover risks.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool#advanced_security_mode",
"platform": "Terraform",
"descriptionID": "f6a7b8c9",
"cloudProvider": "aws",
"cwe": "307",
"riskScore": "5.5",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package Cx

import data.generic.common as common_lib
import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_cognito_user_pool[name]
not common_lib.valid_key(resource, "user_pool_add_ons")
result := {
"documentId": input.document[i].id,
"resourceType": "aws_cognito_user_pool",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_cognito_user_pool[%s]", [name]),
"issueType": "MissingAttribute",
"keyExpectedValue": sprintf("aws_cognito_user_pool[%s].user_pool_add_ons.advanced_security_mode should be ENFORCED or AUDIT", [name]),
"keyActualValue": sprintf("aws_cognito_user_pool[%s].user_pool_add_ons is not defined", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_cognito_user_pool", name], []),
}
}

CxPolicy[result] {
resource := input.document[i].resource.aws_cognito_user_pool[name]
resource.user_pool_add_ons.advanced_security_mode == "OFF"
result := {
"documentId": input.document[i].id,
"resourceType": "aws_cognito_user_pool",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_cognito_user_pool[%s].user_pool_add_ons.advanced_security_mode", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_cognito_user_pool[%s].user_pool_add_ons.advanced_security_mode should be ENFORCED or AUDIT", [name]),
"keyActualValue": sprintf("aws_cognito_user_pool[%s].user_pool_add_ons.advanced_security_mode is OFF", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_cognito_user_pool", name, "user_pool_add_ons", "advanced_security_mode"], []),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "aws_cognito_user_pool" "pass" {
name = "my-user-pool"

user_pool_add_ons {
advanced_security_mode = "ENFORCED"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "aws_cognito_user_pool" "fail" {
name = "my-user-pool"

user_pool_add_ons {
advanced_security_mode = "OFF"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"queryName": "Beta - Cognito User Pool Advanced Security Disabled",
"severity": "MEDIUM",
"line": 1,
"filename": "positive1.tf"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ CxPolicy[result] {
"keyExpectedValue": sprintf("'aws_ecs_service[%s].network_configuration.assign_public_ip' should be set to 'false'(default value is 'false')", [name]),
"keyActualValue": sprintf("'aws_ecs_service[%s].network_configuration.assign_public_ip' is set to true", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_ecs_service", name, "network_configuration", "assign_public_ip"], []),
"remediation": json.marshal({
"before": "true",
"after": "false",
}),
"remediationType": "replacement",
}
}

Expand All @@ -37,5 +42,10 @@ CxPolicy[result] {
"keyExpectedValue": sprintf("'module[%s].%s.%s.assign_public_ip' should be set to 'false'(default value is 'false')", [name,block,service]),
"keyActualValue": sprintf("'module[%s].%s.%s.assign_public_ip' is set to true", [name,block,service]),
"searchLine": common_lib.build_search_line(["module", name, block, service, "assign_public_ip"], []),
"remediation": json.marshal({
"before": "true",
"after": "false",
}),
"remediationType": "replacement",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "2fb51f09-ac2b-4424-a394-a20c61fdde77",
"queryName": "Beta - ECS Task Definition Without Read-Only Root Filesystem",
"severity": "HIGH",
"category": "Insecure Configurations",
"descriptionText": "ECS container definitions should set readonlyRootFilesystem to true to prevent containers from writing to the root filesystem, limiting the blast radius of a container compromise and preventing persistent malware installation.",
"descriptionUrl": "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_security",
"platform": "Terraform",
"descriptionID": "c9d0e1f2",
"cloudProvider": "aws",
"cwe": "732",
"riskScore": "7.0",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package Cx

import data.generic.common as common_lib
import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_ecs_task_definition[name]
defs := json.unmarshal(resource.container_definitions)
container := defs[_]
not common_lib.valid_key(container, "readonlyRootFilesystem")
result := {
"documentId": input.document[i].id,
"resourceType": "aws_ecs_task_definition",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_ecs_task_definition[%s].container_definitions", [name]),
"issueType": "MissingAttribute",
"keyExpectedValue": sprintf("aws_ecs_task_definition[%s] container_definitions should have readonlyRootFilesystem: true", [name]),
"keyActualValue": sprintf("aws_ecs_task_definition[%s] has a container without readonlyRootFilesystem defined", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_ecs_task_definition", name, "container_definitions"], []),
}
}

CxPolicy[result] {
resource := input.document[i].resource.aws_ecs_task_definition[name]
defs := json.unmarshal(resource.container_definitions)
container := defs[_]
container.readonlyRootFilesystem == false
result := {
"documentId": input.document[i].id,
"resourceType": "aws_ecs_task_definition",
"resourceName": terra_lib.get_resource_name(resource, name),
"searchKey": sprintf("aws_ecs_task_definition[%s].container_definitions", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_ecs_task_definition[%s] containers should have readonlyRootFilesystem: true", [name]),
"keyActualValue": sprintf("aws_ecs_task_definition[%s] has a container with readonlyRootFilesystem: false", [name]),
"searchLine": common_lib.build_search_line(["resource", "aws_ecs_task_definition", name, "container_definitions"], []),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_ecs_task_definition" "pass" {
family = "my-task"
container_definitions = jsonencode([{
name = "my-container"
image = "nginx:latest"
essential = true
readonlyRootFilesystem = true
}])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_ecs_task_definition" "fail" {
family = "my-task"
container_definitions = jsonencode([{
name = "my-container"
image = "nginx:latest"
essential = true
readonlyRootFilesystem = false
}])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"queryName": "Beta - ECS Task Definition Without Read-Only Root Filesystem",
"severity": "HIGH",
"line": 1,
"filename": "positive1.tf"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "97d14cd6-5d27-466f-ad96-cc2fac23e8be",
"queryName": "Beta - EMR Cluster Local Disk Encryption Disabled",
"severity": "HIGH",
"category": "Encryption",
"descriptionText": "Amazon EMR security configurations should enable local disk encryption for cluster nodes to protect data stored on locally attached disks against unauthorized access.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/emr_security_configuration",
"platform": "Terraform",
"descriptionID": "a1b2c3d4",
"cloudProvider": "aws",
"cwe": "311",
"riskScore": "7.5",
"experimental": "true"
}
Loading
Loading