GitHub Actions Tutorial

Run a Terraform Scan in GitHub Actions
— Step-by-Step 2026 Guide

Gate every infrastructure pull request with automated security checks. Get copy-paste YAML and fail-on-violation patterns for TFGaurd CI integration.

April 6, 2026 TFGaurd Team 11 min read GitHub Actions · CI/CD · Awareness

Running a terraform scan in GitHub Actions is the fastest way to catch cloud misconfigurations before they make it to production. Yet most teams skip this step — relying on manual reviews that miss 80% of real issues.

This tutorial walks through integrating TFGaurd as a CI security gate. You'll get working YAML you can paste directly into your repository, understand --fail-on violation patterns, and learn how to block merges on critical vulnerabilities.

What You'll Build: A GitHub Actions workflow that runs terraform init, generates a plan, and scans it with TFGaurd — blocking the PR if any High or Critical violations are found.

Why CI/CD Is Your Last Line of Defense

According to the 2025 Gartner IaC Security Report, 73% of cloud security incidents trace back to misconfigurations present at code review — but never caught due to no automated gate. A terraform scan in GitHub Actions closes that gap permanently.

  • An S3 bucket created with public access enabled — ships Tuesday, breach discovered Friday.
  • An RDS instance deployed without encryption — compliance audit fails 6 months later.
  • A security group opens port 22 to 0.0.0.0/0 — unnoticed for 4 months.

Real Cost: IBM's 2025 Cost of a Data Breach Report averages $4.9M per incident. A 3-line YAML addition prevents that.

Step-by-Step: TFGaurd GitHub Actions Setup

1 Create the Workflow File

Create .github/workflows/tfgaurd-security.yml in your repository root.

2 Paste the Complete Workflow

This production-ready YAML installs Terraform, generates a plan, exports it to JSON, installs TFGaurd, and scans — correctly ordered.

YAML — .github/workflows/tfgaurd-security.yml name: Terraform Security Gate on: pull_request: branches: [ main, master, develop ] permissions: contents: read pull-requests: write jobs: security-scan: name: TFGaurd Security Analysis runs-on: ubuntu-latest defaults: run: working-directory: ./infra steps: - name: Checkout Code uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.7.5" - name: Terraform Init run: terraform init -backend=false env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Terraform Plan → JSON run: | terraform plan -out=tfplan -input=false terraform show -json tfplan > tfplan.json env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Install TFGaurd run: curl -sSL https://tfgaurd.com/install.sh | bash - name: TFGaurd Security Scan run: tfgaurd scan --file tfplan.json --fail-on high env: TFGAURD_API_KEY: ${{ secrets.TFGAURD_API_KEY }}

3 Configure Repository Secrets

Go to Settings → Secrets and variables → Actions and add your cloud credentials. TFGAURD_API_KEY is optional — the free tier covers all AWS rules.

Fail-on-Violation Patterns

The --fail-on flag controls which severity level causes TFGaurd to exit non-zero, blocking the PR merge.

Shell # Block on CRITICAL only (good starting point) tfgaurd scan --file tfplan.json --fail-on critical # Block on HIGH and above (recommended for production) tfgaurd scan --file tfplan.json --fail-on high # Block on MEDIUM and above (regulated industries) tfgaurd scan --file tfplan.json --fail-on medium # Audit mode — report only, never fails pipeline tfgaurd scan --file tfplan.json --fail-on none

Pro Tip: Start with --fail-on critical in week one. Move to --fail-on high after teams clear their backlog. Most enterprise teams settle on high as steady-state.

What the Output Looks Like

CI Output ✓ TFGaurd v1.0 • Rules: 1247 • Loaded in 0.3s ✓ Parsed 31 resource changes from tfplan.json [CRITICAL] aws_s3_bucket.data_lake S3 bucket has public access enabled Fix: Set block_public_acls = true [HIGH] aws_security_group.bastion Unrestricted SSH (0.0.0.0/0) on port 22 Fix: Restrict cidr_blocks to your VPN CIDR ━━━ Scan Summary: 1 Critical, 2 High, 4 Medium ━━━ Exit code: 1 → Pipeline blocked ✗

Ship Secure Infrastructure Today

TFGaurd is free. Your plan JSON never leaves your runner. No SaaS. No uploads.

Get TFGaurd Free