A comprehensive source code security scanning pipeline combining SAST, SCA, and secrets detection with local LLM triage for prioritized, actionable findings.
ShieldScan is a production-grade DevSecOps pipeline that scans source code repositories for vulnerabilities across three dimensions:
- SAST (Static Application Security Testing) — Code pattern matching for vulnerabilities (SQL injection, XSS, weak crypto)
- SCA (Software Composition Analysis) — Dependency scanning for known CVEs
- Secrets Detection — Hardcoded API keys, tokens, passwords
All findings are automatically categorized and prioritized using a local Ollama Mistral LLM (no API costs, fully offline).
┌─────────────────────────────────────────────────────────────────┐
│ Source Code Repository │
└──────────────────────────┬──────────────────────────────────────┘
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐
│ Semgrep│ │ Trivy │ │Gitleaks │
│ (SAST) │ │ (SCA) │ │(Secrets) │
└────┬───┘ └───┬────┘ └────┬─────┘
│ Code Issues │ CVEs │ Credentials
└────────────────┼─────────────────┘
│
Raw Findings
(JSON)
│
▼
┌──────────────────┐
│ Ollama Mistral │
│ LLM Triage │
└────────┬─────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Critical Medium Low
(Fix Now) (Fix Soon) (Nice-to-Have)
│ │ │
└─────────────┼────────────┘
▼
┌───────────────────┐
│ Markdown Report │
│ + JSON Data │
└───────────────────┘
| Feature | Description |
|---|---|
| SAST | Semgrep pattern matching for code vulnerabilities (OWASP Top 10) |
| SCA | Trivy scans dependencies for known CVEs with NVD data |
| Secrets | Gitleaks detects hardcoded API keys, tokens, credentials |
| LLM Triage | Local Ollama Mistral categorizes findings by severity |
| CI/CD Ready | GitHub Actions workflow included for automated scanning |
| Containerized | Dockerfile with all tools pre-installed |
| Offline | Local LLM means no external API calls (no costs, full privacy) |
- Python 3.11+
- Semgrep — SAST scanner (install via
pip install semgrep) - Trivy — SCA scanner
- Gitleaks — Secrets scanner
- Ollama — Local LLM runtime (required for full functionality)
- Mistral 7B model (download:
ollama pull mistral)
- Docker (all tools pre-installed in image)
# Clone repository
git clone https://github.com/sedat4ras/ShieldScan.git
cd ShieldScan
# Create virtual environment
python -m venv venv && source venv/bin/activate # macOS/Linux
# python -m venv venv && .\venv\Scripts\activate # Windows
# Install Python dependencies
pip install -r requirements.txt
# Install Semgrep
pip install semgrep
# Install Trivy (macOS)
brew install trivy
# Or download from: https://github.com/aquasecurity/trivy/releases
# Install Gitleaks (macOS)
brew install gitleaks
# Or download from: https://github.com/gitleaks/gitleaks/releases
# Install Ollama
# Download from: https://ollama.ai
# Then: ollama pull mistral && ollama serve# Build (one time, ~2 min first build)
docker build -t shieldscan:latest .
# Scan a repository — mount it read/write so reports can be written back
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$(pwd)":/work \
shieldscan:latest /work
# With Ollama on the host: add --network=host so the container
# can reach http://localhost:11434
docker run --rm --network=host \
--user "$(id -u):$(id -g)" \
-v "$(pwd)":/work \
shieldscan:latest /workThe image runs as a non-root user (shield, UID 10001), so either pass
--user "$(id -u):$(id -g)" (Docker) or --userns=keep-id:uid=10001,gid=10001
(rootless Podman) so the container process can write reports back to the
bind-mounted directory.
# First-time setup
ollama pull mistral # Downloads Mistral 7B model (~4GB)
# Start the Ollama server
ollama serve
# Ollama will be available at http://localhost:11434cd ShieldScan
python main.py
# When prompted, enter:
# Target path: . (current directory)
# or: /path/to/repository- Semgrep scans code patterns (30-60 seconds)
- Trivy checks dependencies for CVEs (15-30 seconds)
- Gitleaks searches for hardcoded secrets (5-10 seconds)
- Ollama Mistral categorizes findings and generates report (30-45 seconds)
Total time: ~2-3 minutes for typical repo
Output:
security_report_[timestamp].md— Human-readable findings with remediation stepsfindings_[timestamp].json— Structured JSON data for SIEM integration
If Ollama is not available, ShieldScan automatically generates a structured report without LLM categorization:
# Even without Ollama, scanner works:
python main.py
# → Semgrep + Trivy + Gitleaks still run
# → Report generated without LLM triage
# ⚠️ Less sophisticated categorization, but still usefulFallback report includes:
- SAST counts and findings
- Vulnerable package list
- Secrets summary
- ✅ Still produces markdown + JSON output
# Security Scan Report
## Executive Summary
- SAST Issues: 3
- Vulnerable Dependencies: 2
- Secrets Found: 0
## 🔴 Critical Issues
- Potential SQL Injection in app.py:42
Severity: High
Fix: Use parameterized queries (prepared statements)
- AWS credentials in .env (hardcoded)
Severity: Critical
Fix: Use environment variables or AWS IAM roles
## 🟡 Medium Issues
- Outdated Flask dependency (1.0 → 2.3)
Fix: pip install --upgrade flask
Impact: Known vulnerabilities in request handling
## 🟢 Low Issues
- Unused import in utils.py
Fix: Remove unused importsFor production use with guaranteed tool availability, use the shipped image. See Installation → Option B for the run commands.
The Dockerfile is a 3-stage build (scanners / pydeps / runtime):
- Base:
python:3.11.16-slim-trixie, non-root usershield(UID 10001) - Pinned: Semgrep 1.174.0, Trivy 0.74.0, Gitleaks 8.30.1
- Runtime footprint: ~770 MB, only
git+ca-certificateson top of the Python slim - No apt repos for third-party tools — release tarballs pulled directly from GitHub, so upstream apt-key / signed-by churn cannot break the build
The design and trade-offs are written up in docs/writeup-dockerfile-and-ci.md.
Every push and pull request against main runs the GitHub Actions workflow at
.github/workflows/ci.yml:
| Job | What it does |
|---|---|
Lint Dockerfile |
Hadolint against the Dockerfile |
Build image |
docker/build-push-action@v6 with the GHA layer cache, exports the built image as a job artifact |
Smoke test |
Loads the artifact, verifies Semgrep / Trivy / Gitleaks are on PATH inside the container, runs an end-to-end scan against a fixture, asserts both reports are produced |
Typical run time: ~3 minutes end-to-end from a cold cache.
- Detects: Code vulnerabilities using pattern matching
- Output: OWASP Top 10 categories (injection, XSS, insecure crypto, etc.)
- Config: Uses
p/owasp-top-tenrulesets
- Detects: Known CVEs in package dependencies
- Scans: requirements.txt, package.json, pom.xml, etc.
- Data: Updated daily from NVD (National Vulnerability Database)
- Detects: Hardcoded secrets (API keys, tokens, passwords)
- Patterns: GitHub/AWS/Slack/private keys, etc.
- Severity: All secrets marked CRITICAL
- Runs locally: Zero API costs, 100% private
- Model: Mistral 7B (8GB VRAM, ~30s response time)
- Function: Reads all scanner outputs → produces prioritized report
What changed:
| Aspect | v1 | v2 |
|---|---|---|
| Scanner | Nmap port scan | SAST/SCA/Secrets |
| AI Usage | GPT-3.5 emoji ratings | Ollama LLM triage |
| Analysis | "Port 22 is risky 🔴🔴🔴" | Real vulnerability logic |
| Report | PDF only | Markdown + JSON |
| Cost | OpenAI API $$$ | Free (local Ollama) |
| Speed | Fast | 2-3 min per scan |
| Target | Network scanning | Source code analysis |
Old code location: old_code/ (v1 archived for reference)
ShieldScan has been tested with mock vulnerability data:
$ python3 -c "
from src.semgrep_runner import run_semgrep
from src.llm_triage import triage_findings
# Test passed: module imports, logic flow, report generation ✅
"Test results:
- ✅ All modules import correctly
- ✅ LLM triage logic executes (with fallback)
- ✅ Report generation works
- ✅ Fallback mode active when Ollama unavailable
"Ollama not running"
ollama serve # Start in separate terminal"Ollama running but model not installed"
ollama pull mistral # Download ~4GB Mistral 7B model"Semgrep not found"
pip install semgrep
semgrep --version"Trivy not found"
- macOS:
brew install trivy - Linux: https://github.com/aquasecurity/trivy#installation
- Windows: Download binary from releases
"Gitleaks not found"
- macOS:
brew install gitleaks - Linux/Windows: https://github.com/gitleaks/gitleaks#installation
Docker build fails
docker build --no-cache -t shieldscan:latest ."ModuleNotFoundError: No module named 'src'"
# Make sure you're running from repo root:
cd /path/to/ShieldScan
python main.pyThis tool implements the DevSecOps principle of "shift-left" security — catching issues before they reach production. Compared to v1 (which used raw Nmap output + GPT emoji ratings), v2:
- ✅ Uses real vulnerability scanners (not just port lists)
- ✅ Implements genuine logic (CVE correlation, pattern matching)
- ✅ Categorizes findings properly (by type, severity, package)
- ✅ Local LLM triage (no external API, no costs)
- ✅ Production-ready (CI/CD, Docker, JSON exports)
MIT — See LICENSE file
GitHub: sedat4ras/ShieldScan | Email: sudo@sedataras.com
