Skip to content

cloudformation-validate

License Main CI CodeQL inspect.software Offline

Latest release crates.io version npm version Maven Central PyPI version Go Reference

Rust toolchain Node.js Python Go JVM

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), a Python package, a Go module, and a JVM library (Kotlin/Java) - all backed by the same validation core.

Features

  • 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.
  • Additional schemas. Merge your own CloudFormation resource provider schemas on top of the bundled ones, so templates using properties or values CloudFormation has not published yet validate cleanly (--additional-schema, or EngineConfig.schema_validator_config.additional_schemas when embedding).
  • 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, Python, Go, or the JVM.
  • Sub-second validation for typical templates.

How it works

When a template is submitted, cloudformation-validate runs a fixed pipeline:

  1. 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.
  2. 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).
  3. 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.
  4. Validate Step Functions - check AWS::StepFunctions::StateMachine definitions (state types, StartAt/Next references, required fields).
  5. 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.

Installation

Use the prebuilt CLI, embed the Rust library, or install a published language binding; this source repository is not required.

Interface Published artifact Install
CLI binary GitHub Releases Download the newest binary for Linux, macOS, or Windows
Rust library crates.io: cloudformation-validate cargo add cloudformation-validate
Node.js npm: @aws/cloudformation-validate npm install @aws/cloudformation-validate
Python PyPI / TestPyPI beta python3 -m pip install cloudformation-validate
Go Go module go get github.com/aws-cloudformation/cloudformation-validate/src/bindings-go/go@latest
JVM Maven Central: software.amazon.cloudformation:cloudformation-validate implementation("software.amazon.cloudformation:cloudformation-validate:latest.release")

See INSTALLATION.md for platform-specific CLI download instructions, runtime requirements, prerelease channels, version pinning, Maven syntax, and release signature verification.

Quick start

# 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/

Embedding as a library

Add the library facade:

[dependencies]
cloudformation-validate = "1.10.0"

Construct an engine and a schema validator once, then validate many templates:

use cloudformation_validate::{
    EngineConfig, RegoEngine, SchemaValidator, ValidateConfig, validate_bytes_with_path,
};

let schema_validator = SchemaValidator::default();
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();
from cloudformation_validate import RegoEngine

engine = RegoEngine()
report = engine.validate_standard("template.yaml")
for d in report.diagnostics:
    print(f"[{d.severity.name}] {d.rule_id}: {d.message}")
import cfnvalidate "github.com/aws-cloudformation/cloudformation-validate/src/bindings-go/go"

engine, err := cfnvalidate.NewRegoEngine(nil)
if err != nil {
    log.Fatal(err)
}
defer engine.Destroy()

report, err := engine.ValidateStandardFile("template.yaml", nil)
for _, d := range report.Diagnostics {
    fmt.Printf("[%s] %s: %s\n", d.Severity, d.RuleID, d.Message)
}

JVM Java/Kotlin (bindings-jvm)

import software.amazon.cloudformation.validate.*
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}")
}

Rules

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.

Modules

This is a Cargo workspace. The main crates:

Crate Role
cfn-validate cfn-validate CLI
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 reporting types: Diagnostic, 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
data-source Build-time pipeline: downloads and processes CloudFormation schemas, generates the validation artifacts baked into the binary

Security

If you discover a potential security issue, please do not open a public GitHub issue. Report it privately through AWS Vulnerability Reporting instead.

License

Licensed under the Apache License 2.0. See NOTICE for attributions and THIRD-PARTY-LICENSES.txt for third-party license details.

Releases

Packages

Used by

Contributors

Languages