skills/terraform-security/SKILL.md
Terraform security practices: sensitive variables, secret management, state protection, .gitignore patterns, and CI/CD credential handling. Trigger: When handling secrets in Terraform, configuring state backends, reviewing .gitignore for Terraform, or setting up CI/CD pipelines for infrastructure.
npx skillsauth add 333-333-333/agents terraform-securityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
.gitignore for a Terraform directoryterraform plan/apply| File/Pattern | Why | Consequence if Leaked |
|-------------|-----|----------------------|
| *.tfvars | Contains actual secret values | Full credential exposure |
| *.tfstate / *.tfstate.backup | Contains ALL resource attributes including secrets in plaintext | Infrastructure takeover |
| .terraform/ | Contains provider binaries and cached state | Potential secret exposure |
These MUST be in .gitignore. No exceptions. Ever.
See assets/gitignore-terraform for the complete
.gitignorepattern.
ANY variable that holds a secret MUST be marked sensitive = true. This prevents Terraform from displaying the value in plan/apply output and logs.
variable "discord_token" {
description = "Discord bot token"
type = string
sensitive = true
}
Terraform will show (sensitive value) instead of the actual value in all output.
| Method | When to Use | Security Level |
|--------|-------------|----------------|
| TF_VAR_ environment variable | CI/CD pipelines, automation | High — never touches disk |
| Secret manager (GCP Secret Manager, Vault) | Production infrastructure | Highest — encrypted, audited, rotated |
| terraform.tfvars file (local only) | Local development only | Medium — on disk but gitignored |
| -var CLI flag | One-off operations | Low — visible in shell history |
| Hardcoded in .tf files | NEVER | Catastrophic — in git forever |
See assets/secret-passing-examples.sh for the patterns.
The Terraform state file contains the full truth about your infrastructure — including every attribute of every resource. For many providers, this includes secrets in plaintext.
Local state (default):
terraform.tfstate in the working directoryRemote state (recommended for teams):
See assets/remote-backend-gcs.tf for the GCS backend configuration.
When running Terraform in CI/CD (GitHub Actions, Cloud Build):
| Rule | Why |
|------|-----|
| Secrets via environment variables only | Never pass via CLI flags (visible in logs) |
| Use TF_VAR_ prefix for Terraform variables | Standard Terraform convention |
| Store secrets in GitHub Secrets / GCP Secret Manager | Encrypted at rest, access-controlled |
| Run plan on PRs, apply only on merge to main | Prevent accidental infrastructure changes |
| Use -input=false flag | Prevent interactive prompts in CI |
| Use -no-color flag | Clean log output |
| NEVER log terraform output with sensitive values | Sensitive outputs leak in CI logs |
See assets/github-actions-terraform.yml for the GitHub Actions workflow.
| Provider | Auth Method | Environment Variable |
|----------|------------|---------------------|
| GCP | Service account key or Workload Identity | GOOGLE_APPLICATION_CREDENTIALS or GOOGLE_CLOUD_PROJECT |
| Discord | Bot token | TF_VAR_discord_token |
| AWS | Access key or IAM role | AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY |
Prefer Workload Identity Federation over service account keys when possible — no long-lived credentials.
Adding a secret to Terraform? → variable with sensitive = true, pass via TF_VAR_
Working alone on non-prod? → Local state is fine (gitignored)
Working in a team? → Remote backend with locking (GCS/S3)
Setting up CI/CD? → GitHub Secrets + TF_VAR_ + plan on PR, apply on merge
Reviewing a PR with .tf changes? → Check for hardcoded secrets, missing sensitive flags
State file accidentally committed? → ROTATE ALL CREDENTIALS IMMEDIATELY, then remove from git history
| File | Description |
|------|-------------|
| assets/gitignore-terraform | Complete .gitignore pattern for Terraform directories |
| assets/secret-passing-examples.sh | How to pass secrets via environment variables and tfvars |
| assets/remote-backend-gcs.tf | GCS remote backend configuration with state locking |
| assets/github-actions-terraform.yml | GitHub Actions workflow for plan on PR, apply on merge |
terraform plan -input=false # Non-interactive plan (for CI)
terraform apply -input=false # Non-interactive apply (for CI)
| Don't | Do |
|-------|-----|
| Hardcode secrets in .tf files | Use sensitive variables + TF_VAR_ env vars |
| Commit *.tfvars with real values | Commit only *.tfvars.example with placeholder values |
| Commit *.tfstate | Add to .gitignore, use remote backend for teams |
| Pass secrets via -var flag | Use TF_VAR_ environment variables |
| Run apply in CI on every push | Run plan on PRs, apply only on merge to main |
| Use service account keys in CI | Use Workload Identity Federation |
| Share state files via Slack/email | Use a remote backend with IAM access control |
| Ignore leaked state file | ROTATE ALL CREDENTIALS immediately |
testing
Review Flutter components and screens for UX/UI compliance. Trigger: When user invokes /ux-review command or requests UX audit.
development
TypeScript strict patterns and best practices. Trigger: When implementing or refactoring TypeScript in .ts/.tsx (types, interfaces, generics, const maps, type guards, removing any, tightening unknown).
testing
Testing philosophy and strategy for every feature: test pyramid, mandatory levels per change type, completion checklist, and skill delegation. Trigger: When planning tests for a feature, reviewing test coverage, defining acceptance criteria, or asking what tests a change needs.
development
Terraform code conventions: file organization, naming, variables, outputs, formatting, and the plan/apply workflow. Trigger: When writing Terraform files, reviewing HCL code style, organizing .tf files, or adding new Terraform modules.