[BUG] Capitalized YAML booleans ('True', 'TRUE', 'Yes', etc.) are parsed as strings, causing false-positive rule failures
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 88/100
Research direction
Start with guard/src/rules/libyaml/loader.rs and the boolean cases in guard/src/rules/libyaml/loader_tests.rs. Run the loader tests first, then verify the listed capitalized YAML values become MarkedValue::Bool and that the tests fail explicitly for any other value type. Done means boolean equality rules validate these values without a String/Bool mismatch.
Written by the indexing model from the issue text.
Description
Describe the bug
In YAML templates, capitalized boolean values such as True, TRUE, Yes, YES, False, FALSE, No, and Off are parsed as MarkedValue::String rather than MarkedValue::Bool.
Consequently, any rule performing boolean equality (== true or == false) against these fields fails due to a type mismatch between String and Bool.
Root Cause
PR #633 introduced is_bool_true and is_bool_false in guard/src/rules/libyaml/loader.rs:
fn is_bool_true(&self, s: &str) -> bool {
matches!(s, "true" | "yes" | "on" | "y")
}
fn is_bool_false(&self, s: &str) -> bool {
matches!(s, "false" | "no" | "off" | "n")
}
s is compared case-sensitively without being converted to lowercase. As a result, "True", "TRUE", "Yes", etc., fail the match and fall through to MarkedValue::String(val, location) at line 94.
Why existing tests in loader_tests.rs did not catch this:
In guard/src/rules/libyaml/loader_tests.rs:
#[rstest::rstest]
#[case::standard_lowercase_true("true", true)]
#[case::standard_capitalized_true("True", true)]
#[case::standard_uppercase_true("TRUE", true)]
...
fn test_handle_bool_happy_path(#[case] arg: &str, #[case] expected: bool) -> Result<()> {
let docs = format!("check: {arg}");
let mut loader = Loader::new();
match loader.load(String::from(docs))? {
MarkedValue::Map(map, ..) => {
assert!(map.len() == 1);
let (.., result) = map.first().unwrap();
if let MarkedValue::Bool(result, ..) = *result {
assert_eq!(result, expected);
}
}
_ => unreachable!("this isn't possible"),
}
Ok(())
}
Because the assertion is wrapped inside if let MarkedValue::Bool(result, ..) = *result, when arg is "True" or "TRUE", *result is MarkedValue::String("True"). The if let condition silently fails to match, the assertion is skipped, and the test exits Ok(()).
To Reproduce
Template (template.yaml):
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
Enabled: True
Rules (rule.guard):
let s3 = Resources.*[ Type == 'AWS::S3::Bucket' ]
rule check_bucket_encryption when %s3 !empty {
%s3.Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.Enabled == true
}
Command:
cfn-guard validate --data template.yaml --rules rule.guard
Result:
The check fails with a comparison failure between String("True") and Bool(true).
Expected Behavior
True, TRUE, Yes, On, False, FALSE, No, Off should parse as MarkedValue::Bool.
Proposed Fix
- In
guard/src/rules/libyaml/loader.rs:
fn is_bool_true(&self, s: &str) -> bool {
matches!(s.to_ascii_lowercase().as_str(), "true" | "yes" | "on" | "y")
}
fn is_bool_false(&self, s: &str) -> bool {
matches!(s.to_ascii_lowercase().as_str(), "false" | "no" | "off" | "n")
}
- In
guard/src/rules/libyaml/loader_tests.rs:
Replace the vacuousif letwith an explicit match assertingMarkedValue::Bool:
match *result {
MarkedValue::Bool(result, ..) => assert_eq!(result, expected),
ref other => panic!("expected MarkedValue::Bool, got {:?}", other),
}
- Dominant language
- Rust
- Stars
- 1.4k
- Forks
- 197
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 5
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aws-cloudformation/cloudformation-guard
-
Difficulty 4/5 3-5 days Newbie friendliness 68/100
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 55/100
aws-cloudformation/cloudformation-guard#659 · 2 comments ·
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 45/100
-
guidance
Difficulty 3/5 1-2 days Newbie friendliness 32/100
aws-cloudformation/cloudformation-guard#652 · 1 comment ·
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 45/100
All issues in aws-cloudformation/cloudformation-guard
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100