What is cfn-lint?
cfn-lint is an open-source tool from AWS that validates CloudFormation templates against the CloudFormation resource specification. It catches errors before deployment and enforces best practices for template authoring.
How the starter kit uses cfn-lint
- Local validation: Run
./scripts/validate-templates.shto validate all templates before committing changes - CI enforcement: The deploy workflow runs cfn-lint before any Rain deployment. Failing checks block the pipeline
- VS Code integration: Pair with the CloudFormation Linter extension for real-time validation while editing
Running cfn-lint manually
The starter kit validation script includes cfn-lint:
./scripts/validate-templates.sh
Or run cfn-lint directly on specific templates:
# Validate a single template
cfn-lint templates/oidc-provider.yml
# Validate all templates
cfn-lint templates/*.yml
# Validate with specific configuration
cfn-lint --config .cfnlintrc templates/*.yml
Common issues detected
cfn-lint catches a wide range of template issues:
Missing required properties
# Bad: Missing required properties
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
# BucketName is optional, but let's say we want encryption
BucketEncryption:
ServerSideEncryptionConfiguration:
# Missing required Rules property
Error: E3002: Invalid property for resource
Invalid property values
# Bad: Invalid property value
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.invalid # Invalid instance type
Error: E3030: Value must be one of the allowed values
Incorrect intrinsic functions
# Bad: Using Ref instead of GetAtt
Resources:
Bucket:
Type: AWS::S3::Bucket
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Statement:
- Effect: Allow
Principal: "*"
Action: s3:GetObject
Resource: !Ref Bucket # Should use !GetAtt Bucket.Arn
Error: E1012: Ref is not valid for resource type
AWS service limits
# Bad: Exceeds parameter limit
Parameters:
Param1:
Type: String
# ... 200+ parameters (limit is 200)
Error: E2500: Template contains more than 200 parameters
Region-specific resources
# Bad: Resource not available in specified region
Resources:
Cluster:
Type: AWS::ECS::Cluster
# Some older regions don't support certain features
Warning: W3045: Resource not available in all regions
Configuration
The starter kit includes a .cfnlintrc file. For details on the default configuration and how to customize it, see the cfn-lint configuration section.
Configuration file format
Create a .cfnlintrc file in YAML or JSON format:
# .cfnlintrc
templates:
- templates/*.yml
- templates/*.yaml
ignore_templates:
- templates/experimental/*.yml
regions:
- us-east-1
- eu-west-1
ignore_checks:
- E3001 # Skip specific rule
- W* # Skip all warnings
include_checks:
- I # Include informational checks
configure_rules:
E3012:
strict: false
Configuration options explained
templates
Glob patterns for templates to validate:
templates:
- templates/*.yml
- stacks/**/*.yaml
ignore_templates
Exclude specific templates:
ignore_templates:
- templates/experimental/*.yml
- templates/deprecated/*.yaml
regions
Validate against specific regions:
regions:
- us-east-1
- eu-west-1
Templates are checked for region-specific resource availability.
ignore_checks
Skip specific rules by ID:
ignore_checks:
- E3001 # Specific error
- W* # All warnings
- I* # All info messages
include_checks
Include additional check types:
include_checks:
- I # Informational
- W # Warnings
configure_rules
Fine-tune specific rules:
configure_rules:
E3012:
strict: false
W2001:
strict: true
Rule categories
cfn-lint organizes rules into categories:
- E1xxx — Basic CloudFormation errors (syntax, schema)
- E2xxx — Template structure errors (limits, formatting)
- E3xxx — Resource specification errors (properties, values)
- E4xxx — Function errors (Ref, GetAtt, Sub, etc.)
- W1xxx — Basic warnings
- W2xxx — Template structure warnings
- W3xxx — Resource specification warnings
- I1xxx — Informational messages
Suppressing specific rules
Inline metadata suppression
Suppress rules for specific resources:
Resources:
LegacyBucket:
Type: AWS::S3::Bucket
Metadata:
cfn-lint:
config:
ignore_checks:
- E3001
- W3045
Properties:
BucketName: legacy-bucket
Template-level suppression
Suppress rules for the entire template:
Metadata:
cfn-lint:
config:
ignore_checks:
- W3045
Output formats
Default format
cfn-lint templates/example.yml
Output:
E3001: Invalid Property Resources/Bucket/Properties/InvalidProperty
templates/example.yml:10:7
JSON format
cfn-lint --format json templates/*.yml
Useful for parsing results in scripts or CI/CD.
JUnit format
cfn-lint --format junit templates/*.yml > results.xml
Useful for test reporting systems.
Parseable format
cfn-lint --format parseable templates/*.yml
Easier for tools to parse.
Custom format
cfn-lint --format '{filename}:{location}:{rule_id}:{message}' templates/*.yml
Integration with CI/CD
The GitHub Actions workflow includes cfn-lint as part of the validation stage:
- name: Validate templates
run: ./scripts/validate-templates.sh
This runs cfn-lint on all templates, ensuring validation checks pass before deployment. Failed checks block the pipeline, preventing invalid templates from reaching production.
For complete details on how cfn-lint integrates into the automated workflow, see the CI/CD Workflow documentation.
Integration with VS Code
Install the CloudFormation Linter extension for real-time validation:
- Install the CloudFormation Linter extension
- Install cfn-lint:
pip install cfn-lint - Open any CloudFormation template
- See errors and warnings inline as you type
For more tips on VS Code integration, read our guide on leveling up CloudFormation authoring in VS Code.
Best practices
- Run locally first: Use
./scripts/validate-templates.shbefore committing to catch issues early - Keep cfn-lint updated: Run
pip install --upgrade cfn-lintregularly to get new rules and resource specs - Review all errors: Don't ignore errors—they usually indicate real problems
- Use VS Code integration: Get real-time feedback while editing templates
- Combine with Checkov: Use both tools together—cfn-lint focuses on correctness while Checkov focuses on security
- Configure for your regions: Set the
regionsoption to validate against your target regions
Troubleshooting
Template not found
# Error: Template file not found
Solution: Check file paths in .cfnlintrc or command line arguments.
Python version issues
cfn-lint requires Python 3.8+:
# Check Python version
python --version
# Upgrade if needed
brew upgrade python # macOS
Outdated resource specs
If cfn-lint doesn't recognize new AWS resources:
# Update cfn-lint
pip install --upgrade cfn-lint
Too many false positives
If specific rules are too strict for your use case:
# Add to .cfnlintrc
ignore_checks:
- W3045 # Skip specific warning
Next steps
Pair cfn-lint with Checkov for comprehensive validation coverage, and review the Scripts reference to see all available validation commands.