RepoPilotOpen in app →

aquasecurity/tfsec

Tfsec is now part of Trivy

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 6w ago
  • 21+ active contributors
  • Distributed ownership (top contributor 34% of recent commits)
Show all 6 evidence items →
  • MIT licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/aquasecurity/tfsec)](https://repopilot.app/r/aquasecurity/tfsec)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/aquasecurity/tfsec on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: aquasecurity/tfsec

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/aquasecurity/tfsec shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 6w ago
  • 21+ active contributors
  • Distributed ownership (top contributor 34% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live aquasecurity/tfsec repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/aquasecurity/tfsec.

What it runs against: a local clone of aquasecurity/tfsec — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in aquasecurity/tfsec | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | Last commit ≤ 73 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>aquasecurity/tfsec</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of aquasecurity/tfsec. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/aquasecurity/tfsec.git
#   cd tfsec
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of aquasecurity/tfsec and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "aquasecurity/tfsec(\\.git)?\\b" \\
  && ok "origin remote is aquasecurity/tfsec" \\
  || miss "origin remote is not aquasecurity/tfsec (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 73 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~43d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/aquasecurity/tfsec"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

tfsec is a static analysis security scanner for Terraform infrastructure-as-code that detects misconfigurations across AWS, Azure, GCP, and other cloud providers. It analyzes HCL files, evaluates Terraform expressions and functions, scans local and remote modules, and applies both built-in rules (hundreds of them) and custom Rego policies. Note: tfsec is now being consolidated into Trivy, Aqua's unified security scanner. Monolithic Go application: cmd/ contains the CLI entry point, internal/ holds the core scanning engine (checks, parser, evaluator), _examples/ contains test Terraform snippets organized by check ID (1000, 1010, etc.), and .github/workflows/ automates testing and releases via GoReleaser. No multi-package structure; checks are registered and stored in-memory during initialization.

👥Who it's for

DevOps engineers, security teams, and infrastructure-as-code developers who write Terraform and need automated pre-deployment security checks to catch cloud misconfigurations before they reach production.

🌱Maturity & risk

Production-ready. tfsec has extensive CI/CD workflows (.github/workflows/ includes test.yml, golangci-lint, release automation), multiple distribution channels (Homebrew, Chocolatey, Docker, AUR, VSCode extension), and is actively maintained by Aqua. However, it is in sunset mode—engineering focus has shifted to Trivy as the long-term platform.

Low technical risk for current use, but strategic risk: tfsec is officially being deprecated in favor of Trivy. Starting new projects with tfsec is discouraged. The codebase itself is stable (large Go codebase with 167k lines, good test coverage via CI), but future updates will be minimal. Dependency maintenance may decline as the team redirects effort.

Active areas of work

The project is in maintenance mode. Active work is moving to Trivy. Recent commits likely focus on bug fixes and compatibility rather than new features. The repository includes a migration guide (tfsec-to-trivy-migration-guide.md referenced in README) encouraging users to transition. GitHub workflows are active (test.yml, release.yml, stale.yml) to keep the project stable but not innovative.

🚀Get running

git clone https://github.com/aquasecurity/tfsec.git
cd tfsec
make install
# or: go build -o tfsec cmd/tfsec/main.go
tfsec --version
tfsec ./path/to/terraform/code

Daily commands:

make test                    # run tests
make build                   # build binary
make install                 # install to $GOPATH/bin
./tfsec --help              # show all scanning options
./tfsec -s                  # run security scanner on current dir

🗺️Map of the codebase

  • cmd/tfsec/main.go: Entry point of the CLI application; defines top-level command parsing and orchestrates the scanner
  • internal/rules/: Core directory containing all built-in security checks organized by cloud provider (aws, azure, gcp, etc.)
  • .github/workflows/test.yml: Defines the continuous integration pipeline; specifies Go version, test commands, and linting rules
  • _examples/: Test fixtures for every check ID; each subdirectory contains vulnerable Terraform code and custom rule definitions
  • Makefile: Development task automation; contains targets for build, test, install, and cross-platform compilation
  • .goreleaser.yml: Defines release automation; configures artifact building, signing, Docker image creation, and distribution channels
  • ARCHITECTURE.md: Explains the codebase design, check structure, and how to extend tfsec with new rules

🛠️How to make changes

Add checks in internal/rules/ (one subdirectory per cloud provider). Add test cases in _examples/{CHECK_ID}/main.tf. Register new checks in the rules initialization code. Modify CLI output formats in internal/formatters/. Add custom Rego policies by editing .tfsec/ config directories in examples. Start by studying _examples/1000/ (custom check example) and internal/rules/ structure.

🪤Traps & gotchas

  1. tfsec is being sunset—do not invest heavily in custom checks or plugins without a migration plan to Trivy. 2. Check IDs are numeric (1000, 1010, etc.) and must be unique; there's no auto-generated registry. 3. Custom Rego policies require understanding of Rego syntax and OPA (Open Policy Agent). 4. The tool outputs multiple formats (JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif); some formatters may have subtle differences in data representation. 5. Scanning remote Terraform modules requires network access and may respect .terraform lockfiles.
  • aquasecurity/trivy — The official successor to tfsec; unified security scanner supporting Terraform, Kubernetes, Docker, and more. All new development is happening here.
  • hashicorp/terraform — The target language/tool being scanned; understanding Terraform's HCL syntax, modules, and functions is essential to building checks.
  • open-policy-agent/opa — Rego policy engine integrated into tfsec for custom rule authoring; knowledge of Rego is required to write advanced policies.
  • terraform-linters/tflint — Alternative Terraform linter for style and best-practice checks; complements tfsec (focuses on configuration quality vs. security).
  • aquasecurity/trivy-checks — Shared check definitions and policies for Trivy; where tfsec's check logic is being ported and maintained long-term.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for custom check loading from .tfsec/custom_tfchecks.yaml

The repo has example configurations in _examples/1607 and _examples/cidrblocks showing custom YAML/JSON check definitions, but there's no clear indication of unit tests validating the custom check parser. Given that custom checks are a feature shown in examples, adding dedicated tests would ensure the YAML/JSON unmarshalling and validation logic is robust and prevent regressions.

  • [ ] Create internal/checks/custom_checks_test.go (or similar) to test parsing of _examples/1607/.tfsec/custom_tfchecks.yaml
  • [ ] Add test cases for malformed YAML/JSON in custom checks to validate error handling
  • [ ] Add test case validating that custom checks properly override or extend default checks
  • [ ] Run tests against both YAML and JSON formats shown in _examples

Add pre-commit hook validation workflow to CI

The repo has .pre-commit-hooks.yaml defined but no CI workflow validates that the pre-commit hooks work correctly on pull requests. This is critical for a tool that markets itself as a pre-commit hook solution. Adding a GitHub Action would catch breakage early.

  • [ ] Create .github/workflows/pre-commit-validation.yml that installs pre-commit and runs hooks against test files in _examples/
  • [ ] Configure the workflow to run on PR events against common file patterns (*.tf, *.json)
  • [ ] Validate that hooks in .pre-commit-hooks.yaml correctly reference the built binary
  • [ ] Document expected behavior in CONTRIBUTING.md

Add integration tests for module resolution across _examples subdirectories (especially _examples/971)

The _examples/971 directory contains a complex module structure with nested paths (modules/azure/storage-account, modules/azure/storage-container) and separate configurations directory. This mirrors real-world Terraform mono-repos, but there's likely no dedicated integration test validating that tfsec correctly resolves and scans modules across different directory levels.

  • [ ] Create tests/integration/module_resolution_test.go (or similar) that runs tfsec against _examples/971
  • [ ] Validate that all checks in the modules/ and configurations/ subdirectories are discovered and reported
  • [ ] Add assertions that module-relative paths are correctly resolved in findings
  • [ ] Test against both relative and absolute path scenarios

🌿Good first issues

  • Add missing test fixtures: Review _examples/ directory and identify check IDs that exist in internal/rules/ but lack corresponding test cases or example Terraform files. Create a PR adding passing and failing .tf examples for an uncovered check.
  • Document check metadata: Many checks lack human-readable descriptions or remediation guidance. Pick 5 checks in internal/rules/, write or improve their documentation, and add examples to the generated docs (likely from a docs/ or mkdocs setup referenced in workflows/mkdocs-latest.yaml).
  • Add a new cloud provider check: Pick a common misconfiguration (e.g., 'S3 bucket without versioning') and implement it following the pattern in internal/rules/aws/. Add test cases in _examples/{NEW_CHECK_ID}/ and verify it passes make test.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • b692c20 — chore(deps): bump golangci-lint to v2.1 (#2176) (mmorel-35)
  • b7128ca — chore(deps): bump golang.org/x/net from 0.33.0 to 0.38.0 (#2174) (dependabot[bot])
  • d17fbf3 — chore: update golangci lint (#2175) (simar7)
  • 473d2c1 — chore: update and clean up golangci-lint (#2165) (mmorel-35)
  • 2b5554d — CVE-2025-22869: Denial of Service in the Key Exchange of golang.org/x/crypto/ssh (#2172) (jdesouza)
  • 1ade121 — chore(deps): bump github.com/go-git/go-git/v5 from 5.11.0 to 5.13.0 (#2164) (dependabot[bot])
  • 7f016e7 — CVE-2024-45337: Misuse of ServerConfig.PublicKeyCallback may cause authorization bypass (#2162) (jdesouza)
  • 6444d31 — chore(deps): bump github.com/open-policy-agent/opa (#2158) (dependabot[bot])
  • 0da0caf — chore(deps): Upgrade deps (jdesouza)
  • 4476b18 — chore(deps): Pin goreleaser (#2149) (simar7)

🔒Security observations

The tfsec repository demonstrates a generally solid security posture with proper use of non-privileged users in Docker and organized CI/CD workflows. However, there are opportunities for improvement: the Dockerfile uses an unpinned 'latest' Alpine tag which could introduce inconsistency and potential vulnerabilities, lacks binary integrity verification, and misses some hardening configurations. The presence of Dependabot configuration and comprehensive testing workflows are positive security indicators. No hardcoded secrets or obvious injection vulnerabilities were detected in the file structure analysis. Recommendations focus on pinning dependencies, implementing checksum verification, and adding Docker security hardening measures.

  • Medium · Docker Image Uses 'latest' Tag — Dockerfile (line 1). The Dockerfile uses 'FROM alpine:latest' which can lead to unpredictable builds and potential security issues. The 'latest' tag is not pinned to a specific version, meaning the base image can change between builds, potentially introducing vulnerabilities or breaking changes. Fix: Pin the Alpine version to a specific release, e.g., 'FROM alpine:3.18' or the latest stable LTS version. Regularly update to patched versions.
  • Low · Missing Security Headers in Docker Configuration — Dockerfile. The Dockerfile does not specify security-related flags or configurations such as READ_ONLY_ROOT_FILESYSTEM or HEALTHCHECK. This reduces the security posture of the containerized application. Fix: Add security hardening directives such as 'RUN chmod -R 555 /usr/bin/tfsec', consider setting 'HEALTHCHECK', and document any required volume mounts as read-only.
  • Low · No Hash Verification for Binary Copy — Dockerfile (line 5: COPY tfsec /usr/bin/tfsec). The Dockerfile copies the tfsec binary without verifying its integrity via checksum validation. This could allow for man-in-the-middle attacks or supply chain compromise if the binary source is compromised. Fix: Implement checksum verification for the tfsec binary before copying, or build from source within the Dockerfile using a multi-stage build approach.
  • Low · Missing Dependency Scanning Configuration — Repository root. No visible dependency lock files (go.sum, go.mod content) or dependency scanning tools configured in the repository structure, making it difficult to track and manage vulnerabilities in third-party packages. Fix: Ensure go.mod and go.sum are committed and up-to-date. Configure automated dependency scanning using tools like Dependabot (partially visible in .github/dependabot.yml) or Snyk.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · aquasecurity/tfsec — RepoPilot