Skip to content

Repository files navigation

πŸ” Secure CI/CD Pipeline with GitHub Actions

A professional, production-ready DevSecOps project demonstrating security vulnerability scanning integrated into a GitHub Actions CI/CD pipeline.


πŸ“‹ Project Overview

This project showcases Shift-Left Security β€” integrating security checks early in the development process through automated CI/CD pipelines. The pipeline automatically scans code for vulnerabilities when changes are pushed, preventing insecure code from reaching production.

🎯 Key Features

  • βœ… Automated Security Scanning: Runs Bandit (Python SAST tool) on every push
  • βœ… Fail-Safe Pipeline: Blocks deployment if high-severity vulnerabilities are detected
  • βœ… Detailed Reporting: Generates JSON and text reports with vulnerability details
  • βœ… DevSecOps Best Practices: Demonstrates industry-standard security workflows
  • βœ… Beginner-Friendly: Simple, well-commented code and workflows
  • βœ… Production-Ready: Includes concurrency controls and proper error handling

πŸ“ Project Structure

secure-cicd/
β”‚
β”œβ”€β”€ README.md                    # This file
β”œβ”€β”€ app.py                       # Sample vulnerable Python Flask app
β”œβ”€β”€ requirements.txt             # Python dependencies
β”‚
└── .github/
    └── workflows/
        └── pipeline.yml         # GitHub Actions workflow (CI/CD pipeline)

πŸš€ Quick Start

1. Prerequisites

  • GitHub account
  • GitHub repository (public or private)
  • Git installed locally

2. Setup Instructions

Step 1: Create a GitHub Repository

# On GitHub, create a new repository named "secure-cicd"
# (or clone this repository)

Step 2: Clone or Initialize Repository Locally

# Option A: Clone if already created on GitHub
git clone https://github.com/<YOUR_USERNAME>/secure-cicd.git
cd secure-cicd

# Option B: Initialize locally and push to GitHub
git init
git remote add origin https://github.com/<YOUR_USERNAME>/secure-cicd.git

Step 3: Add Files to Repository

Copy the following files to your repository:

  • app.py
  • requirements.txt
  • .github/workflows/pipeline.yml

Step 4: Push to GitHub

git add .
git commit -m "Initial commit: Add secure CI/CD pipeline"
git branch -M main
git push -u origin main

Step 5: Verify GitHub Actions

  1. Go to your GitHub repository
  2. Click on the "Actions" tab
  3. You should see the workflow running
  4. Check the logs to see security scan results

πŸ“ File Descriptions

1. app.py - Vulnerable Sample Application

A Flask web application intentionally containing security vulnerabilities for demonstration purposes:

Vulnerabilities Included:

  • ⚠️ Hardcoded Credentials: Database password and API keys exposed in source code
  • ⚠️ Command Injection: subprocess.run() with shell=True and user input
  • ⚠️ Insecure Deserialization: Using pickle.loads() on untrusted data
  • ⚠️ Debug Mode: Flask running with debug=True in production-like environment
  • ⚠️ Insecure Binding: App bound to 0.0.0.0 (all interfaces)
  • ⚠️ Information Disclosure: API endpoints exposing sensitive information

Purpose: Demonstrate what NOT to do, and show how Bandit detects these issues.

2. requirements.txt - Python Dependencies

Specifies Python packages required by the application:

Flask==2.3.2        # Web framework
Werkzeug==2.3.6     # WSGI utilities

3. .github/workflows/pipeline.yml - GitHub Actions Workflow

The main CI/CD pipeline configuration with two jobs:

Job 1: Security Scan (security-scan)

Steps:

  1. Checkout code - Get repository code
  2. Setup Python 3.10 - Configure Python environment
  3. Display Python version - Verify setup
  4. Install Bandit - Install security scanner
  5. Full Bandit scan - Report all vulnerabilities
  6. Strict Bandit scan - Fail on high-severity issues
  7. Parse results - Generate human-readable report
  8. Upload report - Store as GitHub Actions artifact
  9. Check for critical issues - Fail build if needed
  10. Success message - Confirm all checks passed

Job 2: Dependencies Check (dependencies-check)

Additional checks for Python dependencies:

  • Verify requirements.txt exists
  • Check for outdated/vulnerable packages using pip-audit

Key Configuration:

  • Trigger: Runs on push to main and develop branches, and on PRs to main
  • Concurrency: Prevents duplicate workflow runs
  • Continue-on-error: Some steps don't block pipeline (informational only)
  • Artifacts: Generates downloadable security reports

πŸ” Understanding Bandit

What is Bandit?

Bandit is a Python Static Application Security Testing (SAST) tool that scans code for common security issues.

How It Works

# Run full scan (reports all issues)
bandit -r .

# Run strict scan (fails on HIGH severity)
bandit -r . -ll

# Generate JSON report
bandit -r . -f json -o report.json

Severity Levels

  • πŸ”΄ HIGH: Critical security issues (e.g., hardcoded passwords)
  • 🟠 MEDIUM: Significant concerns (e.g., weak cryptography)
  • 🟑 LOW: Minor issues (e.g., debug mode enabled)

πŸ§ͺ Testing the Pipeline

Test Locally (Optional)

Install and run Bandit on your machine:

# Install Bandit
pip install bandit

# Run scan on current directory
bandit -r .

# Run with strict settings
bandit -r . -ll -v

Expected Output

When Bandit scans the vulnerable app.py, it should detect:

>> Issue: [B105:hardcoded_password_string] Possible hardcoded password
   Severity: HIGH   Confidence: MEDIUM
   Location: app.py, line 12

>> Issue: [B602:shell_injection] A shell=True parameter was used with subprocess
   Severity: HIGH   Confidence: HIGH
   Location: app.py, line 33
   
... (more issues)

GitHub Actions Execution

After pushing to GitHub:

  1. Go to Actions tab in your repository
  2. Click on the workflow run
  3. Expand "Security Scan" job to see detailed logs
  4. Check Artifacts section to download the bandit-security-report.json
  5. Pipeline will fail due to detected vulnerabilities (as intended)

πŸ› οΈ Customization

Modify Bandit Strictness

In pipeline.yml, change the Bandit severity level:

# Current: Fails on HIGH and above (-ll)
bandit -r . -ll

# Alternative options:
# -lll     : Only CRITICAL issues (most lenient)
# -ll      : MEDIUM and above
# -l       : All issues including LOW

Add More Steps

Example: Add linting check with Pylint:

- name: Run Pylint
  run: |
    pip install pylint
    pylint app.py || true

Exclude Directories

Bandit scans all files by default. To exclude certain directories:

bandit -r . --exclude ".venv,tests,build"

πŸ“Š Pipeline Workflow Visualization

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Code Pushed to GitHub (main branch)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GitHub Actions Triggered                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β–Ό                     β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ Security    β”‚    β”‚ Dependencies     β”‚
   β”‚ Scan Job    β”‚    β”‚ Check Job        β”‚
   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                  β”‚
    β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚
    β”œβ”€β–Ί Checkout
    β”œβ”€β–Ί Setup Python
    β”œβ”€β–Ί Install Bandit
    β”œβ”€β–Ί Run Full Scan
    β”œβ”€β–Ί Run Strict Scan ──┐
    β”œβ”€β–Ί Parse Results    β”‚
    β”œβ”€β–Ί Upload Report    β”‚
    β”œβ”€β–Ί Check Critical β—„β”€β”˜
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ❌ FAIL (High severity issues found)    β”‚
β”‚ OR                                      β”‚
β”‚ βœ… PASS (No critical vulnerabilities)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”’ Security Best Practices Demonstrated

  1. Shift-Left Security: Security checks run early, not at deployment
  2. Automated Scanning: Human-free, consistent security reviews
  3. Fail-Safe Pipeline: Prevents insecure code from merging
  4. Reporting: Clear, actionable vulnerability reports
  5. Artifact Storage: Historical records for compliance/audit
  6. Concurrency Control: Prevents duplicate runs, saves resources

⚠️ Important Note

This project intentionally contains vulnerable code for educational purposes.

In a real application, you should:

  • βœ… Use secrets management (GitHub Secrets, AWS Secrets Manager)
  • βœ… Sanitize user inputs to prevent injection attacks
  • βœ… Use secure deserialization (JSON instead of pickle)
  • βœ… Disable debug mode in production
  • βœ… Apply least-privilege principles
  • βœ… Run security scanning regularly

πŸ“š Learning Resources


🀝 Contributing

Feel free to extend this project:

  • Add more security tools (Snyk, Trivy, SonarQube)
  • Implement code quality checks (Pylint, Black)
  • Add performance testing
  • Create deployment stages
  • Add notifications (Slack, email)

πŸ“„ License

This project is open source and available under the MIT License.


πŸ“ž Support

For questions or issues:

  1. Check the GitHub Actions logs
  2. Review Bandit documentation
  3. Consult GitHub Actions troubleshooting guides

Happy secure coding! πŸš€

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages