"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.