nadiarahmadinaa/secure-cicd-pipeline
GitHub: nadiarahmadinaa/secure-cicd-pipeline
一套基于GitHub Actions的四层安全CI/CD流水线,通过密钥检测、静态分析、容器扫描和动态测试在代码合并前自动拦截安全漏洞。
Stars: 1 | Forks: 0
# 安全的 CI/CD 流水线
一个 GitHub Actions 流水线,在每次 push 和 pull request 时强制执行**四个自动化安全门**。有漏洞的代码会在合并前被拦截——而不是在部署后被发现。
**在线演示:** 从 `vuln-demo` 分支创建一个 PR,即可看到所有四个门被触发并阻止合并。
## 流水线工作原理
```
Push / Pull Request
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ GATE 1 ── Secrets Detection Gitleaks │
│ Scans full git history for credentials │
│ ↓ BLOCKS on any matched secret │
│ │
│ GATE 2 ── Static Analysis (SAST) CodeQL │
│ Traces data flow for injection, path traversal, etc. │
│ ↓ BLOCKS on error-level findings │
│ │
│ BUILD ─── Docker image docker/build-push-action │
│ Multi-stage, non-root, read-only filesystem │
│ ↓ │
│ │
│ GATE 3 ── Container Scanning Trivy │
│ CVEs in OS packages + pip dependencies │
│ ↓ BLOCKS on unfixed HIGH/CRITICAL CVEs │
│ │
│ GATE 4 ── Dynamic Analysis (DAST) OWASP ZAP │
│ Spins up the live container, active + passive scan │
│ ↓ BLOCKS on FAIL-severity HTTP security alerts │
│ │
│ SUMMARY ─ Aggregated gate result │
│ Required status check → blocks PR merge │
└─────────────────────────────────────────────────────────────────┘
│
▼
✅ Safe to deploy / ❌ Blocked with findings in Security tab
```
所有发现的结果都会以 SARIF 格式上传,并显示在 **GitHub → Security → Code scanning alerts** 中,为这四个工具提供了一个统一的分诊界面。
## 为什么选择这四个工具
每一层都能捕获其他工具遗漏的不同类别的漏洞。
### Gitleaks — 密钥检测
提交到 git 历史中的密钥会永久泄露,即使删除后也是如此。Gitleaks 会针对涵盖 AWS 密钥、GitHub token、私钥、连接字符串等内容的 130 多种模式扫描**整个提交历史**(而不仅仅是 diff)。
它**首先**运行以实现快速失败:如果硬编码的凭据已经存在于代码树中,再花 5 分钟进行 SAST 扫描就毫无意义了。
通过 `.gitleaks.toml` 进行配置,包含针对 Flask `SECRET_KEY`、数据库 URL 和内部 API 密钥的自定义规则,以及用于抑制测试夹具中误报的白名单。
### CodeQL — 静态应用程序安全测试 (SAST)
CodeQL 将代码建模为可查询的数据库,并追踪从不受信任的输入源(HTTP 参数、环境变量)到危险汇聚点的**数据流**(SQL 查询、shell 命令、文件路径)。由于它能理解控制流,因此可以捕获基于正则表达式的扫描器遗漏的漏洞。
使用 `security-extended` 查询套件,涵盖:
- SQL 注入、命令注入、路径遍历
- 硬编码凭据和弱加密
- 不安全的反序列化和不安全的反射
- XSS 和开放重定向
门脚本会解析 SARIF 输出,并在出现任何 `error` 级别的发现时使构建失败。`warning` 级别的发现会在 Security 选项卡中可见,但不会阻止构建。
### Trivy — 容器扫描
容器是一种供应链产物:它捆绑了操作系统、系统库和语言包,其中每一个都可能包含已知的 CVE。Trivy 扫描的是**构建好的镜像**(而不仅仅是 `requirements.txt`),因为操作系统层对基于 pip 的扫描器是不可见的。
三次扫描:
1. **镜像 CVE** — 构建镜像中的操作系统包和 pip 依赖项
2. **文件系统** — 源代码仓库,用于查找密钥和 Dockerfile 配置错误
3. **IaC** — Dockerfile 最佳实践检查(非 root 用户、HEALTHCHECK 等)
该门会在检测到 `HIGH` 和 `CRITICAL` 级别的未修复 CVE 时阻止构建。CVE 例外情况需要在 `.trivyignore` 中添加条目,并附带书面理由和复审日期。
### OWASP ZAP — 动态应用程序安全测试 (DAST)
SAST 分析源代码;DAST 测试的是**运行中的应用程序**。ZAP 能发现仅在运行时出现的漏洞:缺失的安全头、CSRF 暴露、身份验证绕过,以及静态不可见的注入面。
工作流会启动通过了 Trivy 扫描的完全相同的 Docker 镜像(相同的产物),植入测试数据,然后运行基线扫描(被动爬虫 + 主动检查)。警报处理通过 `.github/zap/zap-rules.tsv` 按规则控制:
| 分类 | 效果 |
|---|---|
| `FAIL` | 非零退出 → 流水线被阻止 |
| `WARN` | 记录在报告中,不阻止 |
| `IGNORE` | 完全抑制 |
## 安全门演示
`vuln-demo` 分支包含故意的漏洞,以展示每个门是如何触发的。从它向 `main` 分支发起一个 PR 并观察:
| 安全门 | 发现内容 | 漏洞代码 |
|------|---------|----------------|
| Gitleaks | 硬编码的 API 密钥 | `examples/vulnerable_app.py:7` |
| CodeQL | SQL 注入 (CWE-89) | `examples/vulnerable_app.py:26` |
| CodeQL | 操作系统命令注入 (CWE-78) | `examples/vulnerable_app.py:34` |
| CodeQL | 路径遍历 (CWE-22) | `examples/vulnerable_app.py:40` |
| Trivy | 取决于基础镜像的 CVE 状态 | 镜像扫描 |
| ZAP | 缺少安全头 | 运行时扫描 |
创建演示分支:
```
git checkout -b vuln-demo
# CodeQL 扫描 app/ — 暂时将 examples/vulnerable_app.py 移动或复制到此处
cp examples/vulnerable_app.py app/vulnerable_routes.py
git add app/vulnerable_routes.py
git commit -m "demo: add vulnerable routes to trigger security gates"
git push origin vuln-demo
# 打开 PR: vuln-demo → main
```
## 仓库结构
```
.
├── .github/
│ ├── codeql/
│ │ └── codeql-config.yml # Query suite (security-extended) + path filters
│ ├── scripts/
│ │ └── zap-to-sarif.py # Converts ZAP JSON report → SARIF 2.1.0
│ ├── workflows/
│ │ └── security-pipeline.yml # All four gates + summary job
│ ├── zap/
│ │ └── zap-rules.tsv # Per-alert FAIL / WARN / IGNORE thresholds
│ └── dependabot.yml # Weekly updates: Actions, pip, Docker base image
├── app/
│ ├── app.py # Hardened Flask REST API (the scan target)
│ ├── docker-compose.yml # Local development
│ ├── Dockerfile # Multi-stage, non-root, read-only filesystem
│ └── requirements.txt
├── examples/
│ └── vulnerable_app.py # Annotated vulnerable code — gates demo
├── .gitleaks.toml # Custom rules + allowlist
├── .trivyignore # CVE exceptions (require justification)
├── SECURITY.md # Disclosure policy + gate configuration guide
└── README.md
```
## 目标应用程序演示了什么
`app/app.py` 是一个 Flask REST API,旨在展示默认安全模式——与 `examples/vulnerable_app.py` 形成对比:
| 关注点 | 安全实现 |
|---------|----------------------|
| SQL 查询 | 参数化(`?` 占位符)——不使用字符串格式化 |
| 密码存储 | PBKDF2-SHA256,260,000 次迭代,每用户随机盐 |
| 安全头 | 每次响应都带有 CSP, HSTS, X-Frame-Options, X-Content-Type-Options |
| 速率限制 | 通过 `flask-limiter` 实现的按端点限制 |
| 输入验证 | 在任何处理之前进行长度、类型和字符类别检查 |
| 容器用户 | UID 1001 非root用户,只读文件系统,丢弃所有 capabilities |
## 设置
### 1. 推送到 GitHub
```
git init
git remote add origin https://github.com//secure-cicd-pipeline.git
git add .
git commit -m "feat: secure CI/CD pipeline with four security gates"
git push -u origin main
```
### 2. 启用代码扫描
**Settings → Security → Code security:**
- ✅ Dependency graph
- ✅ Dependabot alerts + security updates
- ✅ Code scanning (CodeQL + Trivy + ZAP SARIF upload here)
- ✅ Secret scanning
### 3. 要求将门作为合并检查
**Settings → Branches → Add rule → `main`:**
```
✅ Require status checks to pass before merging
→ Required check: "Security Gate Summary"
✅ Require branches to be up to date before merging
✅ Require signed commits
✅ Do not allow bypassing the above settings
```
设置完成后,除非所有四个门都通过,否则任何 PR 都无法合并。
### 4. 可选密钥
| Secret | 目的 |
|--------|---------|
| `GITLEAKS_LICENSE` | 高级 Gitleaks 规则集(私有仓库) |
## 本地运行
```
# 启动 API
cd app && docker-compose up --build
# 测试 endpoints
curl http://localhost:5000/health
curl -X POST http://localhost:5000/api/users \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"Str0ng!Pass"}'
curl -X POST http://localhost:5000/api/items \
-H "Content-Type: application/json" \
-d '{"name":"Widget","description":"A test item"}'
# 运行 Gitleaks
docker run --rm -v "$(pwd):/repo" zricethezav/gitleaks:latest \
detect --source=/repo -c /repo/.gitleaks.toml -v
# 运行 Trivy
trivy image --severity HIGH,CRITICAL secure-api:local
# 运行 ZAP baseline
docker run --rm -t ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t http://host.docker.internal:5000 -I
```
## 调整阈值
| 文件 | 更改内容 |
|------|---------------|
| `.github/workflows/security-pipeline.yml` | `FAIL_SEVERITY` 环境变量 (`CRITICAL` / `HIGH` / `MEDIUM`) |
| `.github/codeql/codeql-config.yml` | 查询套件,`paths`,`paths-ignore` |
| `.github/zap/zap-rules.tsv` | 每个警报的 `FAIL` / `WARN` / `IGNORE` |
| `.trivyignore` | 带有理由注释的 CVE 例外情况 |
| `.gitleaks.toml` | 自定义模式和白名单条目 |
## 许可证
MIT
标签:CI/CD安全, Claude, CodeQL, CVE检测, DAST, DevSecOps, Docker, GitHub Actions, Gitleaks, Llama, OWASP ZAP, SAST, StruQ, Web安全, Web截图, 上游代理, 代码安全, 动态应用安全测试, 安全左移, 安全评估工具, 安全防御评估, 容器安全, 恶意软件分析, 漏洞枚举, 盲注攻击, 自动化安全门禁, 自动笔记, 蓝队分析, 请求拦截, 软件供应链安全, 远程方法调用, 逆向工具, 静态应用安全测试