TerraGuard¶
Shift security left. Catch Terraform misconfigurations before they reach production.
TerraGuard is a lightweight static analysis tool for Terraform that identifies high-impact cloud misconfigurations (public storage buckets, overly permissive firewall rules, missing encryption, wildcard IAM policies) at code review time, not after deployment.
Why Before Deployment?¶
Terraform can silently encode dangerous defaults. By the time a misconfiguration surfaces in production: a public S3 bucket, an NSG that allows 0.0.0.0/0, an IAM policy with wildcard actions: the blast radius is real. TerraGuard runs in seconds during a PR, giving engineers and security teams a catch-it-first layer before anything touches infrastructure.
No cloud credentials required. No network calls. Pure static analysis.
Features¶
- Multi-cloud coverage: AWS, Azure and GCP checks out of the box
- CI/CD native: structured exit codes designed for pipeline integration
- SARIF output: plug directly into GitHub Security, Azure DevOps, and other code scanning dashboards
- Configurable thresholds: tune severity levels and exclusion patterns per repo
- Lightweight: minimal Python dependencies, fast cold start
Installation¶
Quick Start¶
# Scan a directory (auto-detects .tf files)
terraguard scan ./infra
# Set a minimum severity threshold
terraguard scan ./infra --severity-threshold medium
# Exclude third-party modules
terraguard scan ./infra --exclude '**/modules/third_party/**'
# Output a SARIF file for code scanning dashboards
terraguard scan ./infra --format sarif > results.sarif
Options¶
| Flag | Description | Default |
|---|---|---|
--severity-threshold |
Minimum level to report: low medium high critical |
low |
--format |
Output format: table json sarif |
table |
--exclude |
Glob pattern to skip (repeatable) | — |
--config |
Path to a YAML config file | — |
-v / --verbose |
Verbose output | off |
Persistent config file¶
Create terraguard.yml in your repo root for settings that apply on every run:
Then run with terraguard scan ./infra --config terraguard.yml.
Security Checks¶
AWS¶
| Rule ID | What it catches | Severity |
|---|---|---|
AWS_S3_PUBLIC |
S3 bucket with public ACL | High |
AWS_S3_ENCRYPTION |
S3 bucket missing server-side encryption | High |
AWS_SG_OPEN |
Security group allows 0.0.0.0/0 to critical ports |
High |
AWS_IAM_WILDCARD |
IAM policy uses wildcard Action or Resource |
High |
AWS_RDS_ENCRYPTION |
RDS instance storage encryption disabled | High |
Azure¶
| Rule ID | What it catches | Severity |
|---|---|---|
AZURE_STORAGE_PUBLIC |
Storage account allows blob public access | High |
AZURE_STORAGE_HTTP |
Storage account allows HTTP (non-TLS) traffic | High |
AZURE_NSG_OPEN |
NSG rule permits inbound from any source | High |
GCP¶
| Rule ID | What it catches | Severity |
|---|---|---|
GCP_GCS_UBA |
GCS bucket disables uniform bucket-level access | High |
GCP_FW_OPEN |
Firewall allows 0.0.0.0/0 to critical ports |
High |
CI/CD Integration¶
GitHub Actions¶
name: TerraGuard
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install terraguard
- run: terraguard scan . --format sarif > results.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
The SARIF upload sends findings directly to the repository's Security → Code scanning tab.
GitLab CI¶
terraguard:
image: python:3.11-slim
script:
- pip install terraguard
- terraguard scan . --severity-threshold high
Pre-commit Hook¶
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: terraguard
name: TerraGuard
entry: terraguard scan
language: python
types: [terraform]
pass_filenames: false
Output Formats¶
Human-readable terminal output with color-coded severity indicators. Default for local use.
Machine-readable output for custom tooling or reporting pipelines:
SARIF 2.1.0 format that integrates with GitHub Security, Azure DevOps, and any SARIF-compatible code scanning platform.
Exit Codes¶
| Code | Meaning |
|---|---|
0 |
No findings at or above the threshold |
1 |
Findings detected — pipeline should fail |
2 |
Tool error (bad arguments, parse failure) |
130 |
Interrupted (SIGINT) |
Predictable exit codes mean TerraGuard works cleanly as a pipeline gate without extra scripting.
Requirements¶
- Python 3.9+
- Dependencies:
python-hcl2,rich,pyyaml
Extending TerraGuard¶
Custom check contributions are documented in DevGuide.md in the repository. The check interface is intentionally simple: a function that receives parsed HCL and returns findings.
MIT License — Copyright © 2026 Skellman.io