{"id":74606,"date":"2025-09-05T01:29:16","date_gmt":"2025-09-04T19:59:16","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=74606"},"modified":"2025-12-26T10:10:15","modified_gmt":"2025-12-26T04:40:15","slug":"automating-docker-image-vulnerability-scanning-with-trivy-in-jenkins","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/automating-docker-image-vulnerability-scanning-with-trivy-in-jenkins\/","title":{"rendered":"Securing CI\/CD Pipelines: Jenkins + Trivy for Container Image Scanning"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>In today&#8217;s DevSecOps pipelines, security can no longer be an afterthought and given short shrift; it must be baked in upfront. Container images, on which today&#8217;s apps are built, include frequently the operating system packages, the third-party libraries, and the app requirements that may come pre-packaged with known vulnerabilities if not properly controlled. These risks can spread unchecked to production infrastructure and endanger critical systems.<\/p>\n<p>To accomplish that, the company needs a reliable means of automatically scanning container images inside their CI\/CD pipelines. <strong>Trivy<\/strong> is one of the most effective tools on the market to accomplish that, which just so happens to be an open-source security and vuln scanner managed by Aqua Security.<\/p>\n<p>Here, we will demonstrate how to integrate <strong>Trivy<\/strong> into a Jenkins pipeline via the official <strong>Trivy<\/strong> Docker image. The process does not include installing anything else on Jenkins agents &#8211; merely Docker &#8211; which makes the solution transportable, scaleable, and simple to maintain on different environments.<\/p>\n<h2>Why Trivy?<\/h2>\n<p>Trivy is widely adopted because it\u2019s:<\/p>\n<ul>\n<li><strong>Agent-independent:<\/strong> May be executed inside a Docker container, which removes the local installation requirements<\/li>\n<li><strong>Comprehensive<\/strong>: Not only vulns, but config issues, secrets, and licenses.<\/li>\n<li><strong>Fast &amp; Efficient<\/strong>: Takes advantage of cached vulnerability databases to accelerate scans.<\/li>\n<li><strong>Flexible<\/strong>: Allows many output formats (table, json, sarif) to devs and integrators.<\/li>\n<li><strong>Developer-friendly<\/strong>: Easily plugs into CI\/CD tools such as Jenkins, GitHub Actions, or GitLab CI.<\/li>\n<\/ul>\n<h2>What Trivy Checks in Container Images<\/h2>\n<p>Scanning images of containers, Trivy has two targets:<\/p>\n<p>1.<strong>Containers within container images<\/strong><br \/>\nContainer images are nothing more than layered files. Installing a package adds new files into the image. Trivy scans the files to check for:<\/p>\n<ul>\n<li><strong>Vulnerabilities<\/strong> \u2192 OS package and app dependency CVEs.<\/li>\n<li><strong>Misconfigurations<\/strong> \u2192 System or application settings security risk.<\/li>\n<li><strong>Secrets<\/strong> \u2192 Hardcoded passwords, tokens, or keys embedded within the files.<\/li>\n<li><strong>Licenses<\/strong> \u2192 Identifies licenses of the dependencies to facilitate checking for compliance.<\/li>\n<\/ul>\n<p>This ensures that the content of the image itself is secure and policy-compliant.<\/p>\n<p>In addition to files, container images also have metadata like configuration, layers, and history. Trivy scans the following metadata to reveal:<\/p>\n<ul>\n<li>Insecure configurations (e.g., running as root). Risk or unnecessary packages.<\/li>\n<li>Risky or unnecessary packages.<\/li>\n<li>Weaknesses in the way the image was built.<\/li>\n<li>By combining these two approaches, <strong>Trivy<\/strong> provides end-to-end visibility into container image risks.<\/li>\n<\/ul>\n<div id=\"attachment_75659\" style=\"width: 929px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-75659\" decoding=\"async\" loading=\"lazy\" class=\" wp-image-75659\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45.png\" alt=\"Trivy Dashboard\" width=\"919\" height=\"479\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45.png 1556w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45-300x157.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45-1024x534.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45-768x401.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45-1536x802.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-31-45-624x326.png 624w\" sizes=\"(max-width: 919px) 100vw, 919px\" \/><p id=\"caption-attachment-75659\" class=\"wp-caption-text\">Trivy Dashboard<\/p><\/div>\n<h2><strong>Jenkins Pipeline Integration<\/strong><\/h2>\n<pre>stage('Scan Docker Image') {\r\n   steps {\r\n      script {\r\n         def image = \"${DOCKER_REGISTRY}\/${DOCKER_REPO}:${IMAGE_VERSION}\"\r\n         sh \"\"\"\r\n         # Pre-download Trivy DB for faster scans\r\n         docker run --rm --network=host -v \/data\/jenkins\/trivy:\/root\/.cache\/trivy aquasec\/trivy image --download-db-only alpine:latest\r\n\r\n         # Run scan and save table format report\r\n         docker run --rm -v \/var\/run\/docker.sock:\/var\/run\/docker.sock -v \/data\/jenkins\/trivy:\/root\/.cache\/trivy -v \\${WORKSPACE}:\\${WORKSPACE} aquasec\/trivy image --timeout 90m --scanners vuln \\\r\n         --format table --output \\${DOCKER_REPO}_\\${IMAGE_VERSION}_trivy-report.txt ${image}\r\n\r\n         # Run scan and save JSON report for Jenkins parsing\r\n         docker run --rm -v \/var\/run\/docker.sock:\/var\/run\/docker.sock -v \/data\/jenkins\/trivy:\/root\/.cache\/trivy -v \\${WORKSPACE}:\\${WORKSPACE} aquasec\/trivy image --timeout 90m --scanners vuln \\\r\n         --format json --output trivy-report.json ${image}\r\n         \"\"\"\r\n         }\r\n\r\n         recordIssues(\r\n         enabledForFailure: true,\r\n         aggregatingResults: false,\r\n         qualityGates: [\r\n         [threshold: 1, type: 'TOTAL_HIGH', unstable: true],\r\n         [threshold: 1, type: 'TOTAL_ERROR', unstable: true],\r\n         [threshold: 5, type: 'TOTAL_NORMAL', unstable: true],\r\n         [threshold: 1, type: 'NEW_HIGH', unstable: true],\r\n         [threshold: 20, type: 'TOTAL', unstable: true]\r\n         ],\r\n        tools: [scanTool(pattern: 'trivy-report.json')],\r\n        id: 'TrivySecurityScan',\r\n        name: 'Trivy Security Scan',\r\n        icon: 'symbol-status-yellow',\r\n        referenceJobName: 'LAST_BUILD',\r\n        healthy: 10,\r\n        unhealthy: 20,\r\n        minimumSeverity: 'NORMAL'\r\n        )\r\n    }\r\n}<\/pre>\n<h2>Pull vs. Build \u2192 Scan \u2192 Push<\/h2>\n<p>You can include Trivy into two typical usage scenarios according to the usage case:<\/p>\n<ol>\n<li><strong>Pull and Scan:<\/strong>\n<ul>\n<li>Apply this when reviewing third-party or base images prior to utilizing them.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Build \u2192 Scan \u2192 Push:<\/strong>\n<ul>\n<li>Popular in CI\/CD pipelines. Assemble your app image, test it against vulnerabilities, and submit it to the registry only if it passes the test.<\/li>\n<li>This ensures that insecure images cannot make it to production.\n<p><div id=\"attachment_75655\" style=\"width: 872px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-75655\" decoding=\"async\" loading=\"lazy\" class=\" wp-image-75655\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15.png\" alt=\"BUILD,SCAN,PUSH\" width=\"862\" height=\"265\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15.png 1907w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15-300x92.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15-1024x315.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15-768x236.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15-1536x473.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/Screenshot-from-2025-09-05-14-32-15-624x192.png 624w\" sizes=\"(max-width: 862px) 100vw, 862px\" \/><p id=\"caption-attachment-75655\" class=\"wp-caption-text\">BUILD,SCAN,PUSH<\/p><\/div><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2>Advantage of This Method<\/h2>\n<ul>\n<li><strong>Agentless deployment:<\/strong> Needs Docker on Jenkins agents only.<\/li>\n<li><strong>Lightweight:<\/strong> You can run the same pipe anywhere\u2014either on-prem or on the cloud.<\/li>\n<li><strong>Shift-left security:<\/strong> Identify vulnerabilities early in the pipeline.<\/li>\n<li><strong>Policy enforcement:<\/strong> Block or build fails if vulns have greater than permissible severity.<\/li>\n<\/ul>\n<h2>How It Works<\/h2>\n<ol>\n<li><strong>Database Pre-Pull<\/strong>\n<ul>\n<li>The Trivy vuln DB is pre-fetched and cached ahead of time at \/data\/jenkins\/trivy so that subsequent scans will be fast.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Dual Output Reports<\/strong>\n<ul>\n<li>Table report (.txt): Developer-friendly human-readable format.<\/li>\n<li>JSON report file format (.json): Programmatically readable Jenkins plugin and dashboard format.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Dockerized Tr<\/strong>\n<ul>\n<li>Utilizes docker run aquasec\/trivy with volumes mounting on Docker socket, cache, and workspace.<\/li>\n<li>No agent startup needed\u2014just Docker.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Quality Gates with recordIssuesJenkins&#8217;<\/strong><br \/>\nWarnings NG plugin checks the JSON output and runs gates:<\/p>\n<ul>\n<li>Fail if HIGH\/CRITICAL Vulnerabilities remain.<\/li>\n<li>Mark unstable if the thresholds are crossed.<\/li>\n<li>Provide Jenkins UI visibility of Trivy Security Scan.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>By incorporating Trivy into Jenkins pipelines via Docker, companies can have all of their container images checked automatically within the CI\/CD process. Because Trivy scans the contents of the file interiors along with the images&#8217; metadata, it has full security coverage.<\/p>\n<p>This configuration allows vulnerable images to be identified early, reports to be seen and auditable, and pipelines to enforce fail-fast policy to avoid insecure deployments.<\/p>\n<p><strong>DevSec is security that is automated and transparent \u2013 and that is exactly what that Jenkins + Trivy pairing offers.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In today&#8217;s DevSecOps pipelines, security can no longer be an afterthought and given short shrift; it must be baked in upfront. Container images, on which today&#8217;s apps are built, include frequently the operating system packages, the third-party libraries, and the app requirements that may come pre-packaged with known vulnerabilities if not properly controlled. These [&hellip;]<\/p>\n","protected":false},"author":1740,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":65},"categories":[2348],"tags":[7159,1883,1682,7942],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74606"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1740"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=74606"}],"version-history":[{"count":6,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74606\/revisions"}],"predecessor-version":[{"id":77122,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74606\/revisions\/77122"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=74606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=74606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=74606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}