Skip to content

Commit 6d0273b

Browse files
committed
fix: copilot issues
Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
1 parent aa66fed commit 6d0273b

3 files changed

Lines changed: 60 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ Policies are written in [Rego](https://www.openpolicyagent.org/docs/latest/polic
2222

2323
Use the standardized per-resource payload generated by the Cloud Custodian plugin as policy input. The plugin evaluates one resource/check pair at a time with `schema_version: v2`; matched resources are marked `assessment.status: non_compliant`, and baseline resources that did not match the Cloud Custodian check are marked `assessment.status: compliant`.
2424

25-
Cloud Custodian policies may include a plugin-only `non_compliance_message` string. When a resource is marked `non_compliant`, that message is appended to the evidence description. The plugin removes this field before executing the policy with Cloud Custodian.
25+
Cloud Custodian policies may include a plugin-only `non_compliance_message` string. When a resource is marked `non_compliant`, that message is appended to the evidence description. The plugin removes this field before executing the Cloud Custodian policy.
2626

2727
Risk templates should dedupe by individual cloud resource using the payload labels `resource_type` and `resource_id`.

policies/cloud_custodian_resources_detected.rego

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import rego.v1
55
violation_id := "cloud_custodian_resource_non_compliant"
66
execution_violation_id := "cloud_custodian_resource_evaluation_failed"
77
unsupported_input_violation_id := "cloud_custodian_unsupported_input"
8+
stderr_max_chars := 500
89

910
_label_schema := [
1011
{
@@ -128,6 +129,22 @@ _default_string(value, fallback) := fallback if {
128129
not is_string(value)
129130
}
130131

132+
_safe_stderr(value) := result if {
133+
first_line := split(value, "\n")[0]
134+
without_control_chars := regex.replace(first_line, "[[:cntrl:]]+", " ")
135+
without_authorization := regex.replace(without_control_chars, "(?i)authorization[[:space:]]*:[[:space:]]*[^[:space:]]+([[:space:]]+[^[:space:]]+)?", "Authorization: <redacted>")
136+
without_secret_values := regex.replace(without_authorization, "(?i)(password|token|secret|access[_-]?key)([[:space:]]*[:=][[:space:]]*)[^[:space:]]+", "$1$2<redacted>")
137+
result := _truncate_error_detail(without_secret_values)
138+
}
139+
140+
_truncate_error_detail(value) := value if {
141+
count(value) <= stderr_max_chars
142+
}
143+
144+
_truncate_error_detail(value) := sprintf("%s...", [substring(value, 0, stderr_max_chars)]) if {
145+
count(value) > stderr_max_chars
146+
}
147+
131148
check_name := _default_string(object.get(_check, "name", ""), "unknown-check")
132149

133150
resource_type := _default_string(object.get(_resource, "type", object.get(_check, "resource", "")), "unknown-resource-type")
@@ -183,7 +200,7 @@ execution_exit_code := object.get(_execution, "exit_code", "unknown-exit-code")
183200

184201
execution_error := _default_string(object.get(_execution, "error", ""), "")
185202

186-
execution_stderr := _default_string(object.get(_execution, "stderr", ""), "")
203+
execution_stderr := _safe_stderr(_default_string(object.get(_execution, "stderr", ""), ""))
187204

188205
execution_errors := object.get(_execution, "errors", [])
189206

policies/cloud_custodian_resources_detected_test.rego

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ test_execution_failure_remark_uses_stderr_when_error_details_are_empty if {
180180
"exit_code": 3,
181181
"error": "",
182182
"errors": [],
183-
"stderr": "access denied reading EC2 instances",
183+
"stderr": "access denied reading EC2 instances\nsecond log line should not be included",
184184
}},
185185
])
186186

@@ -192,6 +192,46 @@ test_execution_failure_remark_uses_stderr_when_error_details_are_empty if {
192192
}]
193193
}
194194

195+
test_execution_failure_remark_redacts_sensitive_stderr_values if {
196+
fixture := object.union_n([
197+
_payload("compliant"),
198+
{"execution": {
199+
"status": "error",
200+
"dry_run": true,
201+
"exit_code": 3,
202+
"error": "",
203+
"errors": [],
204+
"stderr": "Authorization: Bearer secret-token token=abc123 password=hunter2 access_key=AKIAEXAMPLE",
205+
}},
206+
])
207+
208+
violations := cloud_custodian_resources_detected.violation with input as fixture
209+
count(violations) == 1
210+
violations[{
211+
"id": "cloud_custodian_resource_evaluation_failed",
212+
"remarks": "Cloud Custodian policy \"ec2-public-ip-check\" ran with errors while evaluating resource \"aws.ec2/i-123\" (execution_status=\"error\", exit_code=3). Errors: Authorization: <redacted> token=<redacted> password=<redacted> access_key=<redacted>.",
213+
}]
214+
}
215+
216+
test_execution_failure_remark_truncates_long_stderr if {
217+
long_stderr := sprintf("%sDO_NOT_INCLUDE", [concat("", ["x" | some i in numbers.range(1, 520)])])
218+
fixture := object.union_n([
219+
_payload("compliant"),
220+
{"execution": {
221+
"status": "error",
222+
"dry_run": true,
223+
"exit_code": 3,
224+
"error": "",
225+
"errors": [],
226+
"stderr": long_stderr,
227+
}},
228+
])
229+
230+
remarks := cloud_custodian_resources_detected.remarks with input as fixture
231+
contains(remarks, sprintf("Errors: %s...", [concat("", ["x" | some i in numbers.range(1, 500)])]))
232+
not contains(remarks, "DO_NOT_INCLUDE")
233+
}
234+
195235
test_execution_failure_remark_handles_missing_error_details if {
196236
fixture := object.union_n([
197237
_payload("compliant"),

0 commit comments

Comments
 (0)