Fast, offline, embeddable validation for AWS CloudFormation templates.
cloudformation-validate parses a CloudFormation template (JSON or YAML) and returns structured diagnostics — schema
violations, semantic errors, security concerns, and best-practice suggestions — before you deploy. It runs entirely
offline: every rule and resource schema is compiled into the binary, so there is no network access, no credentials, and
no runtime fetching.
It ships as a Rust CLI, an embeddable Rust library, a Node.js package (WASM), and a JVM library (Kotlin/Java) — all backed by the same validation core.
- Offline-first. Rules and AWS resource schemas are baked into the binary. Nothing is fetched at runtime.
- Structured diagnostics. Every finding carries a stable rule ID, severity, precise source span (line/column), resource path, and an optional suggested fix — designed for IDEs, CI, and agents, not just humans.
- Two interchangeable engines. A Rego engine and a CEL engine evaluate the same rule set and produce identical results.
- Custom rules. Extend validation with your own rules in CEL (JSON), Rego, or CloudFormation Guard DSL.
- Embeddable everywhere. Use it from the CLI, Rust, Node.js, or the JVM.
- Sub-second validation for typical templates.
When a template is submitted, cloudformation-validate runs a fixed pipeline:
- Parse — read JSON/YAML, resolve intrinsic functions (
Ref,Fn::GetAtt,Fn::Sub,Fn::If, …), build a reference graph with cycle detection, and model conditions with a SAT solver, producing a semantic model. - Schema validate — check each resource against the compiled CloudFormation provider schemas, producing Fatal-severity diagnostics for structural violations (type mismatches, missing required properties, invalid enums, pattern and constraint failures).
- Evaluate rules — the selected engine (Rego or CEL) evaluates lint rules against the semantic model, producing Error/Warning/Info diagnostics for semantic issues, cross-resource references, security risks, and best practices.
- Validate Step Functions — check
AWS::StepFunctions::StateMachinedefinitions (state types,StartAt/Nextreferences, required fields). - Enrich, filter, report — attach rule descriptions and context, apply include/exclude filters and severity gating, sort by source location, deduplicate, and assemble a structured JSON report.
See INSTALLATION.md for build instructions, prebuilt release artifacts (signed JVM jar, WASM zip,
and per-platform cfn-validate CLI binaries), and signature verification.
# Validate a single template
cargo run -p cfn-validate -- template.yaml
# Validate every template in a directory (recurses, picks up .yaml/.yml/.json)
cargo run -p cfn-validate -- ./templates/
# Use the CEL engine instead of the default Rego engine
cargo run -p cfn-validate -- template.yaml --engine cel
# Compact output for IDEs/CI
cargo run -p cfn-validate -- template.yaml --format standard
# Only report errors and above
cargo run -p cfn-validate -- template.yaml --level error
# List every available rule and exit
cargo run -p cfn-validate -- --list-rules
# Load custom Guard rules
cargo run -p cfn-validate -- template.yaml --guard-rule-source ./my-rules/The CLI prints a JSON report to stdout and exits 0 when clean, 1 when errors or fatal diagnostics are found, and
2 on usage errors. For the full option reference, see the cfn-validate README.
Construct an engine and a schema validator once, then validate many templates:
use rego_engine::RegoEngine;
use schema_validator::SchemaValidator;
use validation_engine::{validate_bytes_with_path, EngineConfig, ValidateConfig};
let schema_validator = SchemaValidator::new();
let engine = RegoEngine::new(EngineConfig::default ()) ?;
let bytes = std::fs::read("template.yaml") ?;
let report = validate_bytes_with_path(
& engine,
& schema_validator,
& bytes,
ValidateConfig::default (),
"template.yaml".to_string(),
) ?;
for d in & report.diagnostics {
println!("[{}] {} — {}", d.severity, d.rule_id, d.message);
}See validation-engine/API.md for the full embedding API.
import { RegoEngine, TemplateFile } from "@aws/cloudformation-validate";
const engine = new RegoEngine();
const report = engine.validateStandard(new TemplateFile("template.yaml"));
for (const d of report.diagnostics) {
console.log(`[${d.severity}] ${d.ruleId}: ${d.message}`);
}
engine.free();import com.amazonaws.cloudformation.validation.*
import java.io.File
val engine = RegoEngine()
val report = engine.validateStandard(File("template.yaml"))
for (d in report.diagnostics) {
println("[${d.severity}] ${d.ruleId}: ${d.message}")
}Bring your own rules in any of three formats — all loadable from the CLI and the library:
- CEL (
.json) — property and data-driven checks, evaluated by the CEL engine. - Rego (
.rego) — complex cross-resource logic, evaluated by the Rego engine. - Guard DSL (
.guard) — declarative compliance rules, translated automatically and usable with either engine.
See RULES and CUSTOM_RULES.md for the formats, available context, and examples.
This is a Cargo workspace. The main crates:
| Crate | Role |
|---|---|
| cfn-validate | cfn-validate CLI and cfn-benchmark binary |
| validation-engine | ValidationEngine trait, orchestration pipeline, Step Functions validation |
| template-model | Template parser, intrinsic resolver, condition SAT solver, reference graph |
| rules | Rule registry, severity model, categories, and diagnostic filtering |
| diagnostics | Shared types: Diagnostic, SourceSpan, ValidationReport, metrics |
| schema-validator | JSON Schema validation against compiled CloudFormation provider schemas |
| rego-engine | Rego-based rule evaluation with custom builtins |
| cel-engine | Native Rust rules plus a CEL interpreter for custom rules |
| guard-translator | Parses Guard DSL into an engine-agnostic intermediate representation |
| bindings-wasm | WASM bindings for Node.js |
| bindings-jvm | JVM bindings (Kotlin/Java) via UniFFI |
If you discover a potential security issue, please do not open a public GitHub issue. Report it privately through AWS Vulnerability Reporting instead.
Licensed under the Apache License 2.0. See NOTICE for attributions and THIRD-PARTY-LICENSES.txt for third-party license details.