AWS CloudFormation Guard is an open source, general purpose policy as code tool. You write rules in its own declarative language and validate JSON or YAML data, such as CloudFormation templates, against them. It does not check template syntax or allowed property values, and it does not enforce anything on the server by itself.
What Guard is
Guard has a command line interface, a domain specific language for rules, and a built in unit testing framework so you can check your rules work as intended. It is not limited to CloudFormation. The documentation says you can validate any JSON or YAML structured data, including CloudFormation change sets, JSON based Terraform configuration files and Kubernetes configurations.
What it does not do
AWS is explicit about two limits:
- Guard does not validate templates for valid syntax or allowed property values. The documentation points to cfn-lint for a thorough inspection of template structure.
- Guard does not provide server side enforcement. For blocking or warning on create, update or delete operations, you use CloudFormation Hooks.
So the pieces fit together like this:
| Job | Tool |
|---|---|
| Is the template well formed? | cfn-lint |
| Does it follow our rules? | Guard on the template |
| Block non compliant operations in the account | A Hook, which can be authored with Guard |
Where Guard fits
The documentation describes three uses:
- Preventative checks before deploy, on templates, change sets, Terraform JSON or Kubernetes config.
- Detective checks on deployed resources, using configuration items from AWS Config.
- Deployment safety, for example checking change sets against rules that stop changes causing replacement, such as renaming a DynamoDB table.
The third is easy to overlook and valuable. A rename that looks harmless in a template can mean a destroyed and recreated table.
A sketch of a rule
This is an illustration of the style, so test it with Guard's own test framework before trusting it:
let buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
rule s3_buckets_have_encryption when %buckets !empty {
%buckets.Properties.BucketEncryption exists
}
AWS's best practice advice is short: write simple rules and use named rules that other rules reference. Complex rules are hard to maintain and test.
A sensible rollout
- Start with a handful of rules on your top risks: encryption, public access, wildcard IAM.
- Run them in pull requests in report only mode, then block.
- Test every rule with passing and failing samples.
- Move the same rules into a Hook if you want account level enforcement.
Quick check
Does Guard replace cfn-lint?
No. The documentation says Guard does not validate syntax or allowed property values and points to cfn-lint for that.
Can Guard block a bad stack update on its own?
No. It has no server side enforcement. Use CloudFormation Hooks, which you can author with Guard rules.
Safeguard runs policies and gates on pull requests, so a failed rule can hold a merge, and its dependency and SBOM scanning covers the packages your infrastructure code pulls in. You can try a free scan at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.