TL;DR β A production-style DevSecOps pipeline embedding automated security scanning at every commit for a fictional fintech startup. Six tools (CodeQL, Bandit, Trivy, Gitleaks, Trivy IaC, Trivy Container) gate every push via GitHub Actions. The
mainbranch is intentionally vulnerable β each gate fails because it detects what it is supposed to detect. Thehardenedbranch is fully remediated β all gates pass. Together they demonstrate the complete security engineering lifecycle: detect, report, fix.
| Branch | Pipeline Status |
|---|---|
main (intentionally vulnerable) |
|
hardened (fully remediated) |
π The
hardenedbranch has GitHub branch protection enforced β all 7 status checks must pass before any merge is permitted.
A production-grade DevSecOps pipeline embedding automated security scanning at every stage of the software development lifecycle β built for a fictional Series A fintech startup, NexusCore Technologies. Demonstrates shift-left security across SAST, SCA, secret detection, IaC scanning, and container security, with a full remediation branch showing how each vulnerability is fixed.
β οΈ Educational repo: NexusCore Technologies is a fictional client. All vulnerabilities are intentional and documented. All credentials are fake dummy values that exist solely to trigger and validate secret detection tooling. See REMEDIATION.md for the hardened versions of every file.
NexusCore Technologies is a fictional Series A fintech startup processing card payments for e-commerce merchants. After three security incidents in Q4 β a leaked API key, a dependency with a known CVE reaching production, and an S3 bucket misconfiguration β their investors demanded a demonstrable improvement in security posture before the Series B round.
The solution was a shift-left security pipeline: rather than running security scans manually before release, every commit now passes through six automated security gates before it can be merged. Developers see findings inline in pull requests. Nothing reaches production without passing all gates.
This repo demonstrates that pipeline end-to-end β including the intentionally vulnerable code that proves each gate catches what it is supposed to catch, and the hardened branch that shows how each finding would be remediated in practice.
| Stage | Tool | Status | Findings |
|---|---|---|---|
| SAST β Semantic Dataflow Analysis | CodeQL | β Passing | SQL Injection, Command Injection, SSTI detected & reported (CodeQL findings are enforced via review in the Security tab rather than by failing the job) |
| SAST β Pattern Matching | Bandit | π΄ Intentionally fails | B201 debug=True, B506 yaml.load, B602 shell=True, B106 hardcoded password detected |
| SCA β Dependency Scanning | Trivy | π΄ Intentionally fails | CVE-2020-14343 (Critical) in PyYAML 5.4.1; vulns in Flask 2.0.1 |
| IaC Security | Trivy IaC | π΄ Intentionally fails | S3 bucket unencrypted; overly permissive security group |
| Secret Detection | Gitleaks | π΄ Intentionally fails | hashicorp-tf-password + generic-api-key detected in source |
| Container Security | Trivy Image | π΄ Intentionally fails | Root user, unpinned base image, unnecessary packages |
| Security Summary | GitHub Actions | β Passing | All SARIF reports uploaded to GitHub Security tab |
Pipeline failures are by design β the repo contains intentionally vulnerable code to demonstrate that each security gate correctly detects and blocks real-world vulnerability classes. The hardened branch shows the remediated versions of every file.
The hardened branch contains the security-engineered versions of every vulnerable file. All security gates pass on that branch.
| File | What changed |
|---|---|
Dockerfile.hardened |
Pinned base image digest, non-root user, removed unnecessary packages, exec form CMD |
src/remediated_app.py |
Parameterised queries, subprocess removed, yaml.safe_load, debug=False, path traversal fix, credentials from env vars |
requirements-hardened.txt |
PyYAML 6.0.2, Flask 3.0.3 β no known CVEs |
terraform/main.tf |
S3 public access blocks enabled, restricted security group, EBS encryption, Secrets Manager |
β Read REMEDIATION.md for the full before/after technical breakdown
All 7 jobs green on the hardened branch. Bandit findings: 0. Gitleaks findings: 0. Every security gate passes after remediation.
Intentional failures on main β Bandit, Trivy SCA, Trivy IaC, Gitleaks, and Container Scan all fail because they detect what they are supposed to detect. Pipeline failures on main are by design.
All SARIF reports from CodeQL, Bandit, Trivy, and Gitleaks feed into the GitHub Security tab β findings visible in one place at the PR level, not buried in CI logs.
Beyond running scanners, this project includes three dedicated security analysis documents authored against the NexusCore threat landscape:
| Document | What it covers |
|---|---|
| STRIDE Threat Register | Full STRIDE analysis across all six categories β Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege β each threat tied to a specific file or component in the repo |
| MITRE ATT&CK Mapping | Pipeline vulnerabilities mapped to MITRE ATT&CK Enterprise techniques β Initial Access, Execution, Persistence, Exfiltration |
| Kill Chain Analysis | Three end-to-end attack chains showing how an attacker could chain the intentional vulnerabilities from initial access to full compromise |
| Tool | Purpose | Stage |
|---|---|---|
| CodeQL | SAST β semantic dataflow analysis. Traces tainted input through call graphs to dangerous sinks. Catches SQL injection, command injection, SSTI, and path traversal at the AST level. Findings are surfaced and triaged via the GitHub Security tab rather than by failing the job directly. | Build |
| Bandit | SAST β fast AST pattern matching. Flags dangerous function calls and insecure patterns instantly: debug=True (B201), yaml.load (B506), shell=True (B602), hardcoded passwords (B106). Complements CodeQL β where CodeQL traces data flow, Bandit flags the call site directly. Standard two-scanner SAST split in UK fintech pipelines. |
Build |
| Trivy | SCA β scans requirements.txt for known CVEs against NVD and OSV databases |
Build |
| Gitleaks | Secret Detection β scans the current working tree as a hard gate and also scans full git history for advisory findings on legacy commits. | Pre-commit / CI |
| Trivy IaC | IaC Security β scans Terraform for misconfigurations against CIS benchmarks | Build |
| Trivy Container | Container image scanning β checks the built Docker image for OS-level CVEs and misconfigurations | Post-build |
| GitHub Security Tab | Centralised SARIF vulnerability reporting β all tool findings visible in one place at the PR level | Post-scan |
graph LR
A[Developer Push] --> B[GitHub Actions]
B --> C[SAST - CodeQL]
B --> D[SAST - Bandit]
B --> E[SCA - Trivy]
B --> F[Secret Scan - Gitleaks]
B --> G[IaC Scan - Trivy]
C --> H[Container Scan - Trivy]
D --> H
E --> H
F --> H
G --> H
H --> I[Security Summary]
I --> J[AWS Deployment]
C --> K[SARIF Upload]
D --> K
E --> K
F --> K
G --> K
H --> K
K --> L[GitHub Security Tab]
Each vulnerability is chosen to exercise a specific security gate. The scanner finding it is the proof the gate works. See REMEDIATION.md for the technical fix and explanation for each one.
- SQL Injection β f-string concatenation in
get_user(). An attacker controls the WHERE clause. - Command Injection β
subprocess.check_output(..., shell=True)in/ping. Shell metacharacters allow arbitrary OS command execution. - Server-Side Template Injection (SSTI) β user input interpolated into a
render_template_string()call. A Jinja2 expression in the URL achieves RCE.
- B201 β
app.run(debug=True)β Flask debug mode exposes the Werkzeug interactive debugger in production. - B506 β
yaml.load()withFullLoaderβ deserialises arbitrary Python objects; CVE-2020-14343. - B602 β
subprocess.check_output(..., shell=True)β shell injection via metacharacters. - B106 β Hardcoded password assigned to
DATABASE_PASSWORD.
- CVE-2020-14343 in PyYAML 5.4.1 β Critical (CVSSv3 9.8) β arbitrary code execution via YAML deserialization.
- Multiple CVEs in Flask 2.0.1.
- S3 bucket with all public access block settings disabled.
- Security group with
0.0.0.0/0on all ports and protocols (ingress and egress). - EC2 root volume with
encrypted = false.
- Fake
hashicorp-tf-passwordinterraform/main.tf. - Fake GitHub PAT (
ghp_format) insrc/vulnerable_app.pyandterraform/main.tfβ detected by Gitleaksgithub-patrule.
- No
USERinstruction β container runs as root. - Unpinned base image (
FROM python:3.9) β mutable tag enables supply chain attacks. - Unnecessary packages installed:
curl,wget,vim,net-tools. - Shell form
CMDβ SIGTERM bypasses the Python process.
The terraform/main.tf in this repo is intentionally minimal β three deliberate misconfigurations included solely to give the IaC scanning stage something to find and validate against. This is a scoping decision, not a gap: a full production Terraform module is out of scope for a pipeline demo project.
For a complete, production-grade AWS security architecture built with Terraform β including VPC design, IAM least-privilege, encrypted S3, CloudTrail, GuardDuty, and full Checkov/tfsec scanning β that work lives in a dedicated project:
β Terraform AWS Security Audit (QuantumTrade)
git clone https://github.com/AurelienKumarathas/devsecops-pipeline-project-1.git
cd devsecops-pipeline-project-1
# Push any change to trigger the full security pipeline
git commit --allow-empty -m "trigger pipeline"
git push
# View scan results in:
# Actions tab β per-job logs
# Security tab β SARIF findings from all toolsTo see the hardened versions of all files:
git checkout hardened
# Dockerfile.hardened and src/remediated_app.py are the remediated files| Skill | Tool / Technique | What it shows |
|---|---|---|
| CI/CD Pipeline Design | GitHub Actions | Multi-job pipeline with parallel execution, dependencies, conditional steps, and SARIF integration |
| SAST β Semantic Analysis | CodeQL | Python dataflow analysis catching injection flaws by tracing tainted input to dangerous sinks |
| SAST β Pattern Matching | Bandit | Fast AST-level detection of dangerous call sites; two-scanner SAST split standard in UK fintech |
| SCA | Trivy | CVE matching against NVD/OSV for direct and transitive dependencies |
| Secret Detection | Gitleaks | Full git history scanning + working tree filesystem scan |
| IaC Security | Trivy IaC | CIS benchmark checks on Terraform before cloud resources are provisioned |
| Container Security | Docker + Trivy | Secure image best practices and OS-level CVE detection |
| Vulnerability Reporting | SARIF + GitHub Security tab | Centralised findings visible in PR reviews, not buried in CI logs |
| Security Engineering | REMEDIATION.md + hardened branch | Demonstrates ability to fix vulnerabilities, not just find them |
| Threat Modelling | STRIDE + MITRE ATT&CK + Kill Chain | Structured threat analysis beyond automated scanning |
| Policy Enforcement | GitHub Branch Protection | All 7 status checks required to pass on hardened β pipeline enforced at the policy level, not just defined |
MIT β see LICENSE for details.


