"Security as Code." An automated pipeline that builds Docker images, scans them for CVEs using Trivy, and acts as a security gate to block vulnerable deployments.
SecOps-Scanner demonstrates a "Shift Left" security approach. Instead of checking for vulnerabilities after deployment, this pipeline integrates auditing directly into the build process.
The Logic:
- Build: Jenkins builds the target application container.
- Scan: Trivy scans the new image for Critical vulnerabilities.
- Gate: If a Critical CVE is found, the pipeline fails intentionally, preventing the insecure code from progressing.
- Orchestrator: Jenkins (Running inside Docker)
- Security Scanner: Trivy (by Aqua Security)
- Containerization: Docker & Docker-in-Docker (DinD)
- Target App: Node.js (Express)
This repository contains the following structure and configurations:
Defines the CI/CD stages: Checkout -> Build -> Scan -> Cleanup.
pipeline { agent any environment { IMAGE_NAME = "trivy-target:${env.BUILD_ID}" DOCKER_DIR = "./app" } stages { stage('Checkout') { steps { echo 'Checkout complete' } } stage('Build Target') { steps { script { echo 'Building the Vulnerable Image...' sh "docker build -t ${IMAGE_NAME} ${DOCKER_DIR}" } } } stage('Security Scan (Trivy)') { steps { script { echo 'Launching Trivy Container...' sh """ docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ aquasec/trivy image \ --exit-code 1 \ --severity CRITICAL \ --no-progress \ ${IMAGE_NAME} """ } } } } post { always { script { sh "docker rmi ${IMAGE_NAME} || true" } } failure { echo 'SECURITY ALERT: Pipeline blocked due to CRITICAL Vulnerabilities.' } success { echo 'Clean Scan: Image is secure.' } } } A simple Node.js app intentionally using an older library to trigger the scanner.
app/server.js
const express = require('express'); const app = express(); app.get('/', (req, res) => res.send('Hello Secure World')); app.listen(3000, () => console.log('App running on port 3000'));app/Dockerfile
FROM node:14-alpine RUN apk add --no-cache curl WORKDIR /usr/src/app COPY package.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "server.js"] Custom image to allow Jenkins to run Docker commands.
FROM jenkins/jenkins:lts-jdk17 USER root RUN apt-get update && \ apt-get install -y docker.io && \ rm -rf /var/lib/apt/lists/* USER jenkins Prepare the custom Jenkins environment that can talk to the host Docker daemon.
docker build -t my-jenkins -f jenkins/Dockerfile . Run Jenkins on port 8080.
docker run \ --name devsecops-jenkins \ --rm \ -d \ -u root \ -p 8080:8080 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ my-jenkins - Open
http://localhost:8080. - Create a New Item -> Pipeline.
- Under Pipeline Definition, select Pipeline script from SCM.
- SCM: Git.
- Repository URL: (Link to this GitHub repo).
- Branch:
*/master(or main). - Script Path:
Jenkinsfile.
When you click Build Now:
- Jenkins builds the Node.js app.
- Trivy detects
CVE-2025-7783(Critical Severity) in theform-datalibrary. - The Build Fails. 🛑
Total: 1 (CRITICAL: 1) Library: form-data (package.json) Vulnerability: CVE-2025-7783 Severity: CRITICAL Status: fixed in 2.5.4 ERROR: script returned exit code 1 Finished: FAILURE This failure is the success criteria. It proves the scanner effectively blocked a vulnerable application from being deployed.