Skip to content

Repository files navigation

DevSecOps Security Pipeline

A production-grade automated security pipeline integrating three SAST/SCA tools into a Jenkins CI/CD workflow. Built and deployed on a real banking application environment.

Every git push automatically triggers a security scan and posts findings as GitLab commit comments within 3 minutes.


Demo

The demo shows the actual HTML report format generated by the pipeline on every build — executive summary, Semgrep findings, CVE list, and SonarQube results.


What this pipeline does

Developer pushes code
        │
        ▼
  GitLab webhook
        │
        ▼
   Jenkins picks up
        │
   ┌────┴──────────────────────────────────────────┐
   │                                               │
   ▼                                               │
Semgrep SAST          ──── findings posted ────▶  │
   │                       as GitLab commit        │
   ▼                       comments                │
Dependency-Check SCA  ──── per tool           ──▶ │
   │                                               │
   ▼                                               │
SonarQube analysis    ──── quality gate       ──▶ │
   │                                               │
   └───────────────────────────────────────────────┘
        │
   Generate 3 HTML reports
   ├── security-report.html   (executive summary)
   ├── semgrep-detail.html    (full Semgrep findings)
   └── dc-report-full.html    (full CVE list)
        │
   Security Gate
   ├── PASSED → ✅ green commit status in GitLab
   └── FAILED → ❌ red commit status + combined reason

Architecture decisions

Shared pipeline — one Jenkinsfile for all projects

The security team maintains one Jenkinsfile in this repository. Every application repository points to it. When the security team updates a rule or adds a tool, it takes effect on every project on their next push — no coordination with development teams required.

Application repositories contain only a 3-line comment Jenkinsfile with no logic.

All stages always run

All stages run regardless of earlier findings. The Security Gate at the end fails with a combined reason covering all tools. Developers see all issues in one push, not one per push.

Three focused reports instead of one large report

Generating one large report that tries to show everything ends up truncating at thousands of CVEs. Instead three separate reports are generated — each focused, complete, and fast to load:

Report Audience Content
security-report.html Management · Auditors · Security team Executive summary, counts, links
semgrep-detail.html Security team · Developers Full Semgrep findings, no truncation
dc-report-full.html Security team All CVEs with filter controls (Dependency-Check native)

NVD database cached locally

Dependency-Check scans use --noupdate — a dedicated daily Jenkins job updates the NVD database at 2am. This keeps pipeline scans at ~30 seconds instead of the 20+ minutes a live database download would take.


Tools

Tool Version Role
Semgrep 1.x SAST — code pattern analysis
OWASP Dependency-Check 12.x SCA — library CVE scanning
SonarQube 10.x CE SAST + quality gate
Jenkins LTS Pipeline orchestration
GitLab CE Source control + webhook trigger

Languages supported

Language Semgrep Dependency-Check SonarQube
PHP p/php + p/owasp-top-ten composer.lock
.NET C# p/csharp packages.lock.json
JavaScript p/owasp-top-ten package-lock.json

Repository structure

.
├── Jenkinsfile                    Main pipeline — all projects point here
├── Jenkinsfile.nvd-update         Daily NVD database update job
├── Jenkinsfile.app-repo-stub      Paste this into application repos
├── generate-report.py             HTML security report generator
├── sonar-project.properties       SonarQube project config template
├── dc-suppressions.xml            Dependency-Check false positive suppressions
│
├── rules/
│   └── custom-security-rules.yml  Custom Semgrep rules (PHP + C#)
│
├── scripts/
│   └── install-tools.sh           Tool installation script (Ubuntu 24.04)
│
├── docs/
│   ├── architecture.md            Pipeline design decisions
│   ├── onboarding.md              How to onboard a new project (3 steps)
│   ├── jenkins-setup.md           Jenkins credentials reference
│   └── tools.md                   Tool configuration and tuning
│
└── demo/
    ├── generate-demo.py           Script that generated the demo report
    └── security-report-demo.html  Demo report with fictional data

Setup

Prerequisites

  • Ubuntu 24.04 LTS server for Jenkins
  • Jenkins LTS installed with plugins: Git, GitLab, Pipeline, SonarQube Scanner
  • SonarQube CE running and accessible
  • GitLab CE running and accessible
  • Java 17+ on the Jenkins server

1 — Install security tools

sudo bash scripts/install-tools.sh

This installs Semgrep, Dependency-Check, and SonarQube Scanner.

2 — Populate the NVD database

Get a free API key: https://nvd.nist.gov/developers/request-an-api-key

/opt/dependency-check/bin/dependency-check.sh \
  --updateonly \
  --nvdApiKey YOUR_API_KEY \
  --nvdApiDelay 6000

This takes 15–20 minutes on first run. Subsequent daily updates take ~2 minutes.

3 — Configure Jenkins credentials

Create these credentials in Jenkins → Manage Jenkins → Credentials:

ID Kind Purpose
jenkins-ci-checkout Username/password Checkout application repos
security-group-token Username/password Checkout this repo
gitlab-api-token Secret text Post GitLab comments
sonarqube-token Secret text SonarQube analysis
sonarqube-read-token Secret text Read SonarQube results
nvd-api-key Secret text NVD database updates
gitlab-webhook-secret Secret text Webhook verification

See docs/jenkins-setup.md for detailed instructions.

4 — Update server addresses

Edit Jenkinsfile and set your server addresses:

environment {
    SONAR_HOST  = 'http://<sonarqube-ip>:9000'
    GITLAB_HOST = 'http://<gitlab-ip>'
    DC_HOME     = '/opt/dependency-check/bin/dependency-check.sh'
}

5 — Create the daily NVD update job

In Jenkins: New Item → Freestyle or Pipeline → Name: dependency-check-db-update

Use Jenkinsfile.nvd-update as the pipeline definition. Set cron trigger: H 2 * * *.

6 — Onboard your first project

Follow the 3-step process in docs/onboarding.md:

  1. Create SonarQube project (2 min)
  2. Create Jenkins pipeline job with 3 parameters (5 min)
  3. Add GitLab webhook (2 min)

Custom Semgrep rules

rules/custom-security-rules.yml contains rules targeting patterns that community rulesets miss. Examples:

  • direct-sql-bypass-orm — detects raw SQL bypassing the ORM layer
  • sensitive-data-in-logs — detects password/PIN/card fields being logged
  • weak-hash-md5 — flags MD5 used for password or data hashing
  • hardcoded-secret — detects API keys and passwords in source code
  • shell-exec-user-input — detects command injection patterns

These rules work on top of the community rulesets — not instead of them.


How findings reach developers

After every push, findings are posted directly to the GitLab commit as comments:

### Semgrep SAST

**Status: FAILED**

#### Blocking findings (ERROR) — 2

- **ERROR** | PaymentController.php line 142 | SQL query built by string concatenation...
- **ERROR** | Dockerfile line 31 | Container runs as root — specify USER directive...

---
_Fix blocking findings before pipeline can pass._

The commit also gets a green ✅ or red ❌ status that appears in merge requests and the repository.


Security note

This repository is sanitised for public sharing. All internal IP addresses, project names, CVE findings, and credentials have been removed. Replace the <placeholder> values in Jenkinsfile with your own environment's addresses before deployment.

Never commit credentials, scan results, or internal project data to this repository.


About

A production-grade automated security pipeline integrating three SAST/SCA tools into a Jenkins CI/CD workflow.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages