Self-hosted service
aquasecurity/tfsec avatar
aquasecurity/tfsec

tfsec: a Terraform security scanner that has been folded into Trivy

Tfsec is now part of Trivy

7,048 stars559 forksGoMIT

At a glance

What is it?
A Go static analyser for Terraform that finds cloud misconfigurations before apply, ships a generated rule library and eight output formats, and now sits in maintenance mode with its future pointed at Trivy.
Who is it for?
tfsec remains a capable Terraform linter with real depth behind its rule set, since the checks are generated from the defsec library and run against evaluated HCL rather than raw text. Its real complication is the one the README puts above the fold: Aqua has consolidated scanning into Trivy and says engineering attention will point there, while tfsec stays available for the time being.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Scanning a directory and failing the build on findings

Usage is one command and one argument. tfsec scans the directory you point it at, and if you give it nothing it uses the current working directory:

bash
tfsec .

The exit status is the whole integration story. It is non-zero when tfsec finds problems and zero otherwise, which means it drops into a CI pipeline without a wrapper script. Nothing needs to parse human-readable output to know whether the build should stop.

The tool describes itself as static analysis of Terraform code to spot potential misconfigurations, and the feature list is more specific than that phrase suggests. It scans local and remote modules, and it evaluates HCL expressions and Terraform functions such as `concat()` rather than only literal values. That distinction is the interesting one. A scanner that only pattern matches on string literals misses every case where a value arrives through a variable or a function, and a config written that way is exactly the config people ship.

It also evaluates relationships between Terraform resources, so a rule can look at more than the block it sits in. Compatibility with the Terraform CDK is listed, which matters for teams generating infrastructure from a typed language rather than writing HAML by hand.

Installing from a package manager, a shell script or the Go toolchain

There are five documented install routes, and the README lists them in the order most people find them. Homebrew and linuxbrew come first, then Chocolatey, then Scoop. On Linux there is a curl-and-bash script:

console
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash

Binaries are also on the releases page. The Go route is the one to know about because of a documented catch attached to it:

bash
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest

`go install` pulls directly from the master branch, so version numbers are not reported by `tfsec --version`. That is a real difference for anyone running a pinned toolchain in CI, where a missing version string removes one of your usual guards.

Release binaries are signed, with the key fingerprint given in the README and the verification steps on a separate `SIGNING.md` page. That is worth more attention than it usually gets: a security scanner that self-updates is a supply chain target, and a scanner that distributes signed binaries without documenting verification is asking you to trust it. The repository tree shows `Dockerfile`, `Dockerfile.ci` and `Dockerfile.scratch` alongside `.goreleaser.yml` and `.goreleaser_github.yml`, so the packaging story is built into the build rather than done by hand.

Four container images for four different jobs

The Docker story is unusually thorough, with a table of four images rather than one. `aquasec/tfsec` on alpine is the normal image. `aquasec/tfsec-alpine` is described as exactly the same thing for people who prefer to be explicit. `aquasec/tfsec-ci` has no entrypoint, which is what you want in a CI build where you need to override the command. `aquasec/tfsec-scratch` is built on scratch for the smallest possible runtime.

The invocation mounts the working directory as `/src`:

bash
docker run --rm -it -v "$(pwd):/src" aquasec/tfsec /src

The base `Dockerfile` in the repository explains why those variants are easy to produce. It copies a prebuilt binary to `/usr/bin/tfsec`, adds a non-privileged user with `adduser -D tfsec`, switches to it, and sets `tfsec` as the entrypoint with `--help` as the default command. Every image therefore starts as a scanner with no shell around it.

For continuous integration there are three named integrations beyond the container image: a GitHub Action at `aquasecurity/tfsec-pr-commenter-action` for commenting on pull requests, an official Azure DevOps task published as `AquaSecurityOfficial.tfsec-official` with its own issue tracker, and editor plugins for JetBrains and VS Code plus a Vim plugin. The editor plugin for VS Code is described as being developed rather than finished, which is a small signal about where the polish sits.

Custom rules in Rego and eight output formats

Two extension points matter more than the rest. The first is custom policy: tfsec applies and embellishes user-defined Rego policies, which means a team can encode an internal rule without forking the scanner. The second is output. The README lists lovely as the default, alongside JSON, SARIF, CSV, CheckStyle, JUnit, text and Gif. That list covers the three consumers people actually have, namely a CI annotation format, a test-report format and something structured to post elsewhere.

Configuration is described as configurable through CLI flags and a config file, and everything the README lists under features is a flag or a config value rather than something hard-coded. Combined with the non-zero exit status, that is a reasonably complete story for CI: pin the config, pick the format, let the exit code decide.

Worth noting is what is not in that list. There is no mention of scanning formats other than Terraform and its modules, no Kubernetes manifests, no CloudFormation, and no serverless or Docker file scanning. Trivy picked up those languages when the scanner was folded in, which is the clearest practical difference between the two tools beyond branding.

Where the rules come from and how to read the codebase

The repository tree is worth reading because it shows how thin tfsec has become. `cmd/` holds the entry points, `internal/` and `utils/` hold the scanning machinery, `version/` the build metadata, `docs/` and `mkdocs.yml` the documentation site, and `test/` the tests. `ARCHITECTURE.md` sits at the top level next to `rules.md` and `CONTRIBUTING.md`, so the project does document its internals rather than leaving you to guess.

The important dependency is `github.com/aquasecurity/defsec` at v0.84.1, and the Makefile has a dedicated `update-defsec` target that runs `go get github.com/aquasecurity/defsec@latest` followed by `go mod tidy`. The rule implementations live in defsec, which is why the scanner binary stays small and why a rule set spans more than one repository. Anyone expecting to add a check by editing this tree will find the actual checks elsewhere.

Other maintenance targets in the Makefile show how the project is worked on. `make test` installs gotestsum if it is missing and runs the suite with the race detector and benchmarks excluded. `make quality` installs golangci-lint at v1.63.4 if absent and runs it, with `pr-ready` chaining quality and typo checking. `make typos` uses codespell with an ignore list in `.codespellignore`, and there is a `.pre-commit-hooks.yaml` so the same checks run before a commit lands. `make image` builds the container image with `TRAVIS_TAG` passed in as a build argument, and `make generate-docs` runs `go run ./cmd/tfsec-docs`.

The migration notice that sits above the overview

The first substantive thing in this README is not a feature, it is a migration notice. tfsec has been folded into Trivy, and the README says so plainly: scanning efforts are being consolidated in one place, tfsec laid the foundations for Trivy's infrastructure-as-code and misconfiguration scanning, and the community is being encouraged to move over. It also states that tfsec will continue to remain available for the time being, although engineering attention will be directed at Trivy going forward.

The three benefits listed for moving are access to more languages and features in the same tool, access to more integrations through the Trivy ecosystem, and commercial support from Aqua alongside the community. Those are real, but the third one changes the nature of the project for anyone who cared that tfsec was a small independent scanner.

There is a dedicated `tfsec-to-trivy-migration-guide.md` at the root of the repository for the command and output mapping, which is the file to read if you already run tfsec. The version numbers frame the timeline: v1.28.14 published on 2025-05-02, preceded by v1.28.13 in January 2025 and v1.28.12 in the same month, with that release consisting of dependency bumps and a fix for CVE-2025-22869 in the SSH key exchange of golang.org/x/crypto. The repository is not archived, its last push is recorded as 2026-03-25, and it has 7,037 stars, 558 forks and 18 open issues.

Editorial conclusion

tfsec remains a capable Terraform linter with real depth behind its rule set, since the checks are generated from the defsec library and run against evaluated HCL rather than raw text. Its real complication is the one the README puts above the fold: Aqua has consolidated scanning into Trivy and says engineering attention will point there, while tfsec stays available for the time being. The last recorded push is 2026-03-25 and the newest listed release is v1.28.14 from 2025-05-02, which tells you what to expect for new rule coverage. If you are starting a Terraform pipeline today, read `tfsec-to-trivy-migration-guide.md` and the `docs/` directory before writing CI around this binary, and if you are keeping it, `ARCHITECTURE.md` and `rules.md` are the two files worth your time.

Frequently asked questions

What is tfsec used for?

tfsec runs static analysis over Terraform code before it is applied, looking for cloud misconfigurations such as publicly exposed storage or weak encryption settings. It ships hundreds of built-in rules covering the major cloud providers, accepts custom rules written in Rego, and exits non-zero when it finds something, which makes it usable directly as a CI gate.

How do I install tfsec on Ubuntu?

The README gives a Linux shell script for this case: `curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash`. You can also pull the `aquasec/tfsec` image and run it against the current directory, or use `go install github.com/aquasecurity/tfsec/cmd/tfsec@latest`, which tracks the master branch and will not report a version.

Should I use tfsec or Trivy for Terraform scanning?

Aqua has consolidated its scanning work into Trivy and asks the tfsec community to migrate, while tfsec stays available. Trivy keeps the same Terraform engine and adds other languages and more integrations. New pipelines are better served by Trivy, and the repository's own migration guide covers moving an existing tfsec setup.

Official sources

  1. aquasecurity/tfsec on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/aquasecurity-tfsec.svg)](https://hysenlabs.com/projects/aquasecurity-tfsec)