Trivy Action: A Wrapper That Puts Trivy's Full CLI Inside a GitHub Action
Project brief: Runs Trivy as GitHub action to scan your Docker container image for vulnerabilities.
At a glance
- What is it?
- aquasecurity/trivy-action wraps the Trivy scanner as a GitHub Action, covering image, filesystem, repo, IaC, and SBOM scans. The core trade-off is configuration flexibility versus setup simplicity, with caching and config-file support as the main differentiators.
- Who is it for?
- Adopt trivy-action if you already run Trivy in CI and want a thin wrapper that handles binary installation, DB caching, and a single input surface. Skip it if you need to run Trivy outside GitHub Actions, if you prefer to pin the binary through a separate setup step, or if you require fine-grained control over cache keys.
- Can I use it commercially?
- Yes. Apache-2.0 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?
- Yes. The repository last received commits 27 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What trivy-action actually does
trivy-action is a GitHub Action that runs the Trivy vulnerability scanner. It is not a new scanner. It is a wrapper that installs Trivy, passes your inputs to the trivy binary, and handles the exit code so the workflow fails when vulnerabilities exceed your threshold. The README positions it for CI pipelines that build a Docker image and then scan it in the same job. That is the primary use case, but the action also supports filesystem scans, git repository scans, rootfs scans, infrastructure-as-code scans, and SBOM generation. The audience is a team that already uses GitHub Actions and wants to add container security scanning without learning Trivy's command-line flags in depth. The wrapper hides the binary invocation behind a small set of inputs like image-ref and scan-type.
The mechanism: inputs, config file, and precedence
The action works by mapping its inputs to Trivy's CLI options. The README shows two usage patterns. The first passes image-ref, format, exit-code, and ignore-unfixed directly as action inputs. The second uses a trivy-config input that points to a trivy.yaml file checked into the repository. That config file can hold any Trivy option, including severity, format, and secret scanning configuration. The action requires three inputs that cannot be set in the config file: scan-type, and either scan-ref or image-ref. Those define what to scan and how. The precedence order follows Viper, the configuration library Trivy uses: action flag wins over environment variable, which wins over config file, which wins over default. That ordering matters. If you set severity in both the action input and the config file, the input wins. If you rely on the config file for most options, you must remember that the action's own inputs override it. This is a clean design for simple cases, but it can confuse teams that expect the config file to be the single source of truth.
Getting it running: a minimal workflow
The README's first example is a complete workflow. It checks out code, builds a Docker image with docker build, and then scans it. The scan step uses aquasecurity/trivy-action@v0.36.0 with image-ref set to the tagged image. The format is table, exit-code is 1, and ignore-unfixed is true. That last input means the workflow fails only on fixed vulnerabilities. To run a filesystem scan instead, you set scan-type to fs and scan-ref to '.'. The action will scan the current directory. If you want to use a config file, you add trivy-config: trivy.yaml. The README gives an example trivy.yaml that sets format to json, exit-code to 1, severity to CRITICAL, and points to a separate secret config. The action also supports a version input to control which Trivy binary version gets installed. By default, the action calls aquasecurity/setup-trivy as its first step, so you do not need a separate setup step. If you already installed Trivy, you can set skip-setup-trivy to true to avoid a redundant install.
Caching: built-in but with branch restrictions
The action has built-in caching for the vulnerability DB, the Java DB, and the checks bundle. The cache is stored in $GITHUB_WORKSPACE/.cache/trivy by default. It restores the cache before the scan and saves it after. This uses actions/cache under the hood but requires less configuration. Caching is on by default, and you can disable it with cache: false. The README warns about rate limiting if you disable it, because Trivy downloads the vulnerability database on each run without a cache. There is a real limitation here. GitHub Actions restricts cache access between branches. A workflow can restore a cache created in the current branch or the default branch, but not from arbitrary branches. If you want to share caches across branches, you need to create the cache in the default branch first. The README suggests a separate cron workflow that updates the cache daily in the default branch, then your scan workflows set TRIVY_SKIP_DB_UPDATE and TRIVY_SKIP_JAVA_DB_UPDATE to avoid downloading the DB again. That is a workable pattern, but it adds a second workflow to maintain. The cache key is not configurable through the action inputs, which limits how you can invalidate caches on new Trivy versions.
A genuine limitation: the wrapper hides the binary version
The action's default setup step installs a Trivy version specified by the version input. The README does not state what the default version is. That is a problem for reproducibility. If you do not pin the version, your scan results can change when the action updates its default, because a newer Trivy may have a different vulnerability database schema or different detection rules. The README shows a manual setup example that pins version v0.74.0, but the action itself does not require you to pin. For a security scanner, reproducibility is not a nice-to-have. You want to know exactly which binary and which database version produced a given report. The action does let you pin, but the default behavior is opaque. Another limitation is that the action only runs on GitHub-hosted or self-hosted runners. It is not a standalone CLI. If you need to scan locally or in another CI system, you should call the trivy binary directly. The wrapper also adds a layer of indirection. When something goes wrong, you have to inspect the action's logs to see the exact trivy command it executed, rather than seeing the command in your workflow file.
Alternatives: setup-trivy plus direct invocation
The most direct alternative is to use aquasecurity/setup-trivy on its own and then run the trivy command in a run step. The README itself shows this pattern in the manual setup section. You call setup-trivy with a pinned version and cache: true, then in a later step you run trivy image --exit-code 1 --ignore-unfixed your-image. That approach gives you full control over the command line, including flags that the action does not expose as inputs. The trade-off is that you must manage the DB download and caching yourself. setup-trivy has a cache input, but it does not handle the Trivy DB cache the same way trivy-action does. Another alternative is to use Trivy's official container image directly in a workflow, mounting the Docker socket and running trivy image. That avoids the action wrapper entirely but requires careful Docker socket handling, which is a security risk on shared runners. The practical difference is configuration effort versus control. trivy-action is the low-effort path; direct invocation is the high-control path.
Maintenance and licensing
The repository is licensed under Apache-2.0, which is permissive and allows commercial use, modification, and redistribution. The action is actively maintained, with releases roughly monthly. The most recent release, v0.36.0, was pushed on 2026-04-22. There are also tagged releases like v0.35.0 and an untagged 0.35.0, which suggests the maintainers use the v prefix consistently for releases. The maintenance cost for you is low: the action is a thin shell script, so the main upkeep is tracking new releases and deciding when to bump the version pin in your workflows. The README does not document a migration path between major versions, but the input surface has been stable in recent releases. The bigger maintenance burden is the Trivy binary itself. As Trivy updates its database format or adds new scan types, you may need to update the action version to stay compatible. The README's use of a trivy.yaml config file means you must keep that file in sync with the Trivy version you pin. A config option that exists in Trivy v0.74.0 may not exist in an older version, and the action will not tell you that until the scan fails.
When this action is the wrong tool
This action is the wrong tool if you need to scan an image that is already in a private registry and you do not want to build it in the same workflow. The README covers private registry scanning, but it still runs inside a GitHub Actions job, which means you must handle registry credentials as secrets. If your CI is not GitHub Actions, the action is useless. It is also a poor fit for teams that need to generate SBOMs in a format that requires custom flags not exposed as inputs. While the action supports SBOM generation, the README does not list all possible Trivy flags as inputs. For advanced use cases, you will end up using the trivy-config file to pass those flags, which works but defeats some of the simplicity the action offers. Finally, if you are scanning a large monorepo with many services, running a separate scan step for each image can slow down your pipeline. The action does not provide a matrix or batch mode; you would need to write that yourself. In those cases, a dedicated Trivy scan job with a script that loops over images might be more efficient.
Editorial conclusion
Adopt trivy-action if you already run Trivy in CI and want a thin wrapper that handles binary installation, DB caching, and a single input surface. Skip it if you need to run Trivy outside GitHub Actions, if you prefer to pin the binary through a separate setup step, or if you require fine-grained control over cache keys. Before adopting, verify that the version you pin matches your Trivy config file syntax, test the exit-code behavior with your severity thresholds, and confirm that the default cache directory works with your self-hosted runner's workspace permissions.
Community notes