How do you configure Trivy for air-gapped environments?
Quick Answer
In air-gapped environments, Trivy operates without internet access by pre-downloading the vulnerability database on a connected machine using trivy image --download-db-only, transferring the database file to the air-gapped system, and configuring Trivy to use the local database with --skip-db-update. Organizations can also host an internal OCI registry mirror to serve the database within the isolated network.
Detailed Answer
Think of configuring Trivy for an air-gapped environment like stocking a remote island medical clinic. The clinic cannot access the mainland pharmacy, so medical supplies must be loaded onto a ship, transported across the water, and unloaded at the island dock on a regular schedule. The clinic operates perfectly well between shipments, but someone must plan the logistics of keeping supplies current. Similarly, Trivy needs its vulnerability database to function, and in an air-gapped network, that database must be transported manually or through a controlled data transfer mechanism.
Air-gapped environments are networks that are physically isolated from the internet, commonly found in government classified systems, financial trading floors, healthcare networks handling PHI, and industrial control systems. Trivy requires a vulnerability database to match installed packages against known CVEs, and by default it downloads this database from an OCI registry at ghcr.io/aquasecurity/trivy-db on every run. In an air-gapped environment, this download fails because there is no outbound internet connectivity. The solution involves three components: downloading the database on a machine with internet access, transferring it to the air-gapped network through an approved data diode or removable media process, and configuring Trivy to use the local database without attempting to update it.
The database download process uses the trivy image --download-db-only command, which fetches the latest vulnerability database and stores it in the Trivy cache directory, typically located at ~/.cache/trivy/db/ on Linux systems. The database consists of two files: trivy.db, which is a BoltDB file containing vulnerability records indexed by package name and version, and metadata.json, which records the download timestamp and database schema version. These files are approximately 40-50 MB compressed and can be transferred via USB drive, one-way data diode, or an approved file transfer system. On the air-gapped side, the files are placed in the Trivy cache directory, and Trivy is invoked with the --skip-db-update flag to prevent it from attempting an internet connection. For the checkout-service scanning pipeline in a classified environment, this means the Jenkins build agent has a local copy of the database that is refreshed weekly through the approved media transfer process.
For organizations that want a more automated approach, hosting an internal OCI registry mirror is the recommended pattern. On the connected side, a scheduled job pulls the Trivy database image from ghcr.io/aquasecurity/trivy-db:2 and pushes it to a staging registry. The database image is then transferred to the air-gapped network's internal registry, such as an instance of Harbor or Artifactory running inside the isolated network. Trivy is configured with the --db-repository flag pointing to the internal registry URL, allowing it to pull the database as if it were operating normally. This approach also applies to the Java database that Trivy uses for scanning Java archives and the checks bundle used for misconfiguration detection. For the inventory-sync service running in a DoD IL5 environment, the internal Harbor instance at registry.internal.mil serves all three databases, and Trivy operates transparently without any special flags beyond the custom repository configuration.
A critical gotcha is database staleness. In a connected environment, Trivy always has access to the latest vulnerability data, but in an air-gapped setup, the database is only as current as the last transfer. A database that is two weeks old might miss recently published CVEs, creating a false sense of security. Establish a regular transfer cadence, ideally daily or at minimum weekly, and include a validation step that checks the metadata.json timestamp to ensure the database is not older than the acceptable threshold. Another common issue is the Java database and checks bundle, which are separate from the main vulnerability database. If you only transfer the main database, Trivy will still attempt to download the Java DB and checks bundle, causing scan failures for Java applications and misconfiguration checks. Use --skip-java-db-update and --skip-check-update flags, and ensure those databases are also transferred. Finally, ensure the Trivy binary itself is updated through the same air-gap transfer process, as older versions may not be compatible with newer database schemas.