-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Describe the issue
When creating a custom check, some of the attributes set in the YAML or the Python don't appear in the output, and it's different for each depending on the method of defined custom policy.
The example below is purely for PoC'ing the efforts, I don't actually want to check this string length :)
I have a simple Terraform Plan JSON:
{
"format_version": "1.2",
"terraform_version": "1.5.7",
"planned_values": {
"root_module": {
"resources": [
{
"address": "random_string.name",
"mode": "managed",
"type": "random_string",
"name": "name",
"provider_name": "registry.terraform.io/hashicorp/random",
"schema_version": 2,
"values": {
"keepers": null,
"length": 8,
"lower": true,
"min_lower": 0,
"min_numeric": 0,
"min_special": 0,
"min_upper": 0,
"number": true,
"numeric": true,
"override_special": null,
"special": false,
"upper": true
},
"sensitive_values": {}
}
]
}
},
"resource_changes": [
{
"address": "random_string.name",
"mode": "managed",
"type": "random_string",
"name": "name",
"provider_name": "registry.terraform.io/hashicorp/random",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"keepers": null,
"length": 8,
"lower": true,
"min_lower": 0,
"min_numeric": 0,
"min_special": 0,
"min_upper": 0,
"number": true,
"numeric": true,
"override_special": null,
"special": false,
"upper": true
},
"after_unknown": {
"id": true,
"result": true
},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"configuration": {
"provider_config": {
"random": {
"name": "random",
"full_name": "registry.terraform.io/hashicorp/random"
}
},
"root_module": {
"resources": [
{
"address": "random_string.name",
"mode": "managed",
"type": "random_string",
"name": "name",
"provider_config_key": "random",
"expressions": {
"length": {
"constant_value": 8
},
"special": {
"constant_value": false
}
},
"schema_version": 2
}
]
}
},
"timestamp": "2025-09-03T19:38:32Z"
}
When I provide this yaml custom policy:
metadata:
name: "Random String Length > 5 YML"
id: "CKV_random_odyssey_1"
category: "NETWORKING"
description: "Ensure random_string resource length is not greater than 5 FROM YML."
severity: "HIGH"
definition:
cond_type: "attribute"
resource_types:
- "random_string"
attribute: "length"
operator: "less_than"
value: 5
And this python test:
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
class RandomStringLengthCheck(BaseResourceCheck):
def __init__(self):
name = "Random String Length > 5"
id = "CKV_random_odyssey_1"
categories = (CheckCategories.NETWORKING,)
supported_resources = ["random_string"]
guideline = "Testing"
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources, guideline=guideline)
def scan_resource_conf(self, conf):
length = conf.get("length")
self.details.append("Ensure random_string resource length is not greater than 5.")
if isinstance(length, list):
length = length[0]
if length is not None and int(length) > 5:
return CheckResult.FAILED
return CheckResult.PASSED
check = RandomStringLengthCheck()
I also have the necessary __init__.py
file in the directory as outlined in the codebase.
My JSON output for the command is this (I omitted the code block because omg lines):
{
"check_type": "terraform_plan",
"results": {
"passed_checks": [],
"failed_checks": [
{
"check_id": "CKV_random_odyssey_1",
"bc_check_id": null,
"check_name": "Random String Length > 5",
"check_result": {
"result": "FAILED",
"evaluated_keys": []
},
"file_path": "/input.json",
"file_abs_path": "/Users/mikesweikata/Documents/repositories/iac-policy/input.json",
"repo_file_path": "/input.json",
"file_line_range": [
13,
26
],
"resource": "random_string.name",
"evaluations": null,
"check_class": "custompy",
"fixed_definition": null,
"entity_tags": null,
"caller_file_path": null,
"caller_file_line_range": null,
"resource_address": "random_string.name",
"severity": null,
"bc_category": null,
"benchmarks": null,
"description": null,
"short_description": null,
"vulnerability_details": null,
"connected_node": null,
"guideline": "Testing",
"details": [
"Ensure random_string resource length is not greater than 5."
],
"check_len": null,
"definition_context_file_path": null
},
{
"check_id": "CKV_random_odyssey_1",
"bc_check_id": null,
"check_name": "Random String Length > 5 YML",
"check_result": {
"result": "FAILED",
"entity": {
"random_string": {
"name": {
"keepers": [
null
],
"length": [
8
],
"lower": [
true
],
"min_lower": [
0
],
"min_numeric": [
0
],
"min_special": [
0
],
"min_upper": [
0
],
"number": [
true
],
"numeric": [
true
],
"override_special": [
null
],
"special": [
false
],
"upper": [
true
],
"__file__": [
"/Users/mikesweikata/Documents/repositories/iac-policy/input.json"
],
"__startline__": [
14
],
"__endline__": [
27
],
"start_line": [
13
],
"end_line": [
26
],
"__address__": "random_string.name",
"__change_actions__": [
"create"
],
"__change_keys__": []
}
}
},
"evaluated_keys": [
"length"
]
},
"file_path": "/input.json",
"file_abs_path": "/Users/mikesweikata/Documents/repositories/iac-policy/input.json",
"repo_file_path": "/input.json",
"file_line_range": [
13,
26
],
"resource": "random_string.name",
"evaluations": null,
"check_class": "checkov.common.graph.checks_infra.base_check",
"fixed_definition": null,
"entity_tags": {},
"caller_file_path": null,
"caller_file_line_range": null,
"resource_address": "random_string.name",
"severity": "HIGH",
"bc_category": null,
"benchmarks": {},
"description": null,
"short_description": null,
"vulnerability_details": null,
"connected_node": null,
"guideline": null,
"details": [],
"check_len": null,
"definition_context_file_path": "/Users/mikesweikata/Documents/repositories/iac-policy/input.json"
}
],
"skipped_checks": [],
"parsing_errors": []
},
"summary": {
"passed": 0,
"failed": 2,
"skipped": 0,
"parsing_errors": 0,
"resource_count": 1,
"checkov_version": "3.2.450"
},
"url": "Add an api key '--bc-api-key <api-key>' to see more detailed insights via https://bridgecrew.cloud"
}
Some of the key attributes between the two outputs are missing. For example, for the YML based policy, I get severity
, but in the Python I don't even though it's set in both. And both outputs are missing the ClassCategories in the output.
Is this a feature break that's needed in the higher tier? Or am I missing something?
I know it's working on ingestion because if I set the attribute incorrectly, checkov
will fail to run.
Additional context
Installed view Brew on an M4 MacBook.