kmathanprasath/sast-triage

GitHub: kmathanprasath/sast-triage

VaultScan 是一个 SAST 告警聚类分诊平台,通过将数百条扫描发现归纳为少数根因模式并借助 AI 生成级联修复建议,帮助团队用最少的修复动作消除最多的安全隐患。

Stars: 0 | Forks: 0

# VaultScan ## 问题所在 每个 SAST 工具都会给你提供数百个发现。 没有人会去阅读这数百个发现。 因此团队选择无视它们,导致技术债不断累积。 真正的问题不在于有 454 个发现。而在于没人注意到那 6 个不断重复的模式。 ``` 454 findings └─ cwe-79 (XSS) → 307 findings across 176 files ← same innerHTML pattern └─ cwe-353 (integrity check) → 128 findings across 68 files ← same missing SRI tag └─ hardcoded-secret → 2 findings in 1 file └─ cwe-95 (eval injection) → 8 findings across 7 files └─ cwe-116 (output encoding) → 8 findings in 1 file └─ cwe-1333 (regex DoS) → 1 finding ``` 只需修复一次 XSS 模式(将 DOMPurify 添加到一个共享 util 中)→ 就能消除 307 个问题。 这正是 VaultScan 所揭示的深刻见解。 ## 功能介绍 ``` Any GitHub/GitLab/Bitbucket repo ↓ Semgrep + SonarQube scan ↓ Two-level root cause clustering (pattern groups → per-file breakdown) ↓ Gemini AI triage "Fix this pattern → cascades to kill N issues across M files" ↓ Compound risk scoring "This pattern is growing 23%/sprint. Fix cost doubles in 42 days." ↓ Dashboard: 6 action items, not 454 noise ``` ## 系统架构 ``` ┌─────────────────────────────────────────────────────────┐ │ Dashboard :3000 │ │ React + TypeScript + Recharts │ │ Overview · Debt Trend · All Findings · Export PDF │ └────────────────────────┬────────────────────────────────┘ │ nginx proxy ┌──────────────┴──────────────┐ ▼ ▼ ┌──────────────────┐ ┌──────────────────────┐ │ Scanner :5000 │ │ Intelligence :8000 │ │ Go + Gin │────────▶│ Python + FastAPI │ │ │ │ │ │ • Semgrep │ │ • Pattern clustering │ │ • SonarQube │ │ • Compound risk │ │ • Deduplication │ │ • Gemini AI triage │ │ • Cron scanner │ │ • TP/FP/FN/TN valid. │ └────────┬─────────┘ └──────────┬────────────┘ │ │ └──────────────┬───────────────┘ ▼ ┌──────────────────┐ │ PostgreSQL :5432 │ │ │ │ • sast │ │ • root_cause_ │ │ clusters │ │ • cluster_history│ ← compound risk │ • digest_reports │ └──────────────────┘ │ ┌──────────────────┐ │ SonarQube :9000 │ │ Community Ed. │ └──────────────────┘ ``` | 服务 | 技术 | 端口 | |--------------|-------------------------|------| | dashboard | React 18 + TypeScript | 3000 | | scanner | Go 1.22 + Gin | 5000 | | intelligence | Python 3.12 + FastAPI | 8000 | | sonarqube | SonarQube 10 CE | 9000 | | postgres | PostgreSQL 15 | 5432 | ## 前置条件 - [Docker Desktop](https://www.docker.com/products/docker-desktop/) 4.x 或更高版本 - 至少 8 GB 内存(仅 SonarQube 就需要约 4 GB) - Git 就这些。无需在本地安装 Go、Python、Node 或 Semgrep。 ## 安装说明 ### 1. 克隆 ``` git clone https://github.com/kmathanprasath/sast-triage cd sast-triage/SAST-Triage ``` ### 2. 配置 ``` cp .env.example .env ``` 打开 `.env` 并填写: ``` # SonarQube 集成所需(首次启动后获取 — 见步骤 4) SONAR_TOKEN= # 可选 — 使用 cascade 解释启用 AI 驱动的分诊 # 在 https://aistudio.google.com/app/apikey 获取免费密钥 GEMINI_API_KEY= # 可选 — 仅在扫描私有 GitHub 仓库时需要 GITHUB_TOKEN= ``` 对于本地开发,其他配置保持原样即可。 ### 3. 启动 ``` docker compose up -d ``` 首次构建需要 3–5 分钟(下载基础镜像、编译 Go、安装 Python 依赖)。 后续启动只需不到 30 秒。 ### 4. 获取 SonarQube token(一次性设置) SonarQube 首次运行启动大约需要 2 分钟。 ``` # 等待直到返回 "UP" curl -s http://localhost:9000/api/system/status | grep status ``` 然后: 1. 打开 http://localhost:9000 2. 登录:`admin` / `admin` → 在提示时修改密码 3. 前往 **My Account → Security → Generate Token** 4. 将其命名为 `vaultscan`,点击 Generate 5. 将 token 复制到你的 `.env` 文件中,作为 `SONAR_TOKEN=squ_xxxxx` 6. 重启 scanner:`docker compose restart scanner` ### 5. 验证一切是否运行正常 ``` make health ``` 预期输出: ``` ✓ Scanner ✓ Intelligence ✓ Dashboard ✓ SonarQube ``` 或者手动检查: - Dashboard:http://localhost:3000 - Scanner API:http://localhost:5000/health - Intelligence API:http://localhost:8000/health - SonarQube:http://localhost:9000 ## 运行你的第一次扫描 ### 通过 Dashboard(推荐) 1. 打开 http://localhost:3000 2. 点击 **New Scan** 3. 粘贴一个 GitHub 仓库 URL(例如 `https://github.com/digininja/DVWA`) 4. 设置分支(例如 `main` 或 `master`) 5. 点击 **Start Scan** 进度弹窗会显示每个阶段:Cloning → Semgrep → SonarQube → Unifying → Clustering → Done。 ### 通过 CLI ``` # 触发扫描 curl -X POST http://localhost:5000/scan \ -H 'Content-Type: application/json' \ -d '{"repo_url":"https://github.com/digininja/DVWA","branch":"master"}' # 返回: {"scan_id":"abc-123", "status_url":"/scan/abc-123"} # 轮询状态 curl http://localhost:5000/scan/abc-123 # 完成后,查看模式摘要 curl http://localhost:8000/digest/digininja-DVWA | python3 -m json.tool ``` ### 通过 Makefile ``` # 扫描仓库 make scan REPO=https://github.com/digininja/DVWA BRANCH=master # 获取摘要 make digest SERVICE=digininja-DVWA # 获取债务趋势 make trend SERVICE=digininja-DVWA # 使用 DVWA 进行完整的端到端测试 make test-e2e ``` ## Dashboard 功能 ### 概览选项卡 - **KPI 条** — 发现总数、不同模式数、所需的最小修复次数、AI 分类状态 - **模式摘要** — 每行是一个漏洞模式,而不是单个发现 - “XSS 模式 → 消除 176 个文件中的 307 个问题” - 展开可查看:级联解释、根本修复、精确的代码指导 - **漏洞分布** — 按规则系列的饼图 + 条形图 - **修复覆盖率** — 显示通过修复列出模式所解决问题的百分比的进度条 - **验证** — 将每个模式标记为 TP / FP / FN / TN,并持久化到数据库 - **导出 PDF** — 包含所有模式、级联解释和验证状态的完整报告 ### 技术债趋势选项卡 - 每个集群在 Sprint 间的爆炸半径增长情况 - 对加速增长的集群标记倍增时间估算 - “今日修复成本:MEDIUM → 30 天后修复成本:HARD” ### 所有发现选项卡 - 所有 254 个集群(按文件细分),支持分页 - 每行均可展开:显示每个具体发现的行号、CWE、描述 - 理由:“修复此文件可消除 N 个问题,因为同一模式在行 X、Y、Z 处重复出现” - 按验证状态筛选(All / Unreviewed / TP / FP) ## 聚类是如何工作的 VaultScan 使用两层聚类模型: **第 1 层 — 模式组**(开发者所看到的) - 按漏洞模式(规则系列)对所有发现进行分组 - 一个模式 = 一个可在所有受影响文件中级联应用的修复操作 - 454 个发现 → 6 个模式 **第 2 层 — 文件集群**(深入查看) - 每个模式组内的按文件细分 - 在“All Findings”选项卡中用于准确显示需要修改的文件 - 454 个发现 → 254 个文件级集群 **Gemini 的作用**:为每个模式组生成一个可到处级联应用的根本修复方案,并用通俗易懂的英语解释为什么修复一次就能解决所有实例。 ## 复合风险评分 VaultScan 的创新之处。每次扫描都会追加到 `cluster_history` 中,从而实现 Sprint 间的增长跟踪: ``` Growth rate: +23%/sprint Projected next: 72 issues (up from 58) Doubles in: 42 days Fix cost today: MEDIUM (3 hours) Fix cost in 30d: HARD (3 days) Urgency score: 9/10 ← ACCELERATING ``` 这回答了团队从未问过的问题:“如果我们今天无视它,情况会变得多糟?” ## 环境变量 | 变量 | 是否必填 | 描述 | |---|---|---| | `DB_USER` | 否 | PostgreSQL 用户名(默认:`debtscan`) | | `DB_PASSWORD` | 否 | PostgreSQL 密码(默认:`debtscan123`) | | `DB_NAME` | 否 | PostgreSQL 数据库名(默认:`debtscan`) | | `SONAR_TOKEN` | 推荐 | SonarQube 用户 token — 启用 SonarQube 分析 | | `GEMINI_API_KEY` | 可选 | Google Gemini API key — 启用带级联解释的 AI 分类 | | `GITHUB_TOKEN` | 可选 | GitHub PAT — 用于私有 GitHub 仓库扫描所必需。需要 `repo`(读取)权限范围 | | `GITLAB_TOKEN` | 可选 | GitLab 个人访问令牌 — 用于私有 GitLab 仓库所必需。需要 `read_repository` 权限范围 | | `BITBUCKET_TOKEN` | 可选 | Bitbucket 应用密码 — 用于私有 Bitbucket 仓库所必需。需要 `repository`(读取)权限 | | `SEMGREP_RULES` | 否 | Semgrep 规则集(默认:`auto`) | | `SEMGREP_APP_TOKEN` | 可选 | 用于托管规则的 Semgrep Cloud token | | `SCAN_CRON_ENABLED` | 否 | 启用计划扫描(默认:`true`) | | `SCAN_CRON_SCHEDULE` | 否 | Cron 表达式(默认:`0 3 * * *` — 每天凌晨 3 点) | ## API 参考 ### Scanner (端口 5000) | 方法 | 端点 | 描述 | |--------|----------|-------------| | POST | `/scan` | 触发扫描 `{"repo_url":"...","branch":"..."}` | | GET | `/scan/:id` | 轮询扫描状态 | | GET | `/scan/:id/report` | 完整的统一发现报告 | | GET | `/scan/:id/report/download` | 下载 JSON 格式的报告 | | DELETE | `/scan/:id` | 删除一次扫描 | | GET | `/scans` | 列出所有扫描 | | POST | `/microservice` | 注册仓库用于 cron 扫描 | | GET | `/cron/status` | Cron 调度器状态 | | GET | `/health` | 健康检查 | ### Intelligence (端口 8000) | 方法 | 端点 | 描述 | |--------|----------|-------------| | GET | `/digest/:service` | 带有 AI 级联解释的模式摘要 | | GET | `/debt-trend/:service` | Sprint 间的复合风险数据 | | GET | `/all-findings/:service` | 包含每次发现细分的所有集群 | | GET | `/summary` | 包含紧急程度评分的所有服务 | | POST | `/recluster/:service` | 强制重新聚类 + 重新评分 + 重新分类 | | PATCH | `/validate/:cluster_id` | 设置 TP/FP/FN/TN 验证状态 | | GET | `/validations/:service` | 获取某个服务的所有验证状态 | | GET | `/health` | 健康检查 | ## 私有仓库 VaultScan 支持 GitHub、GitLab 和 Bitbucket 上的私有仓库。 **方式 1 — 单次扫描 token(Dashboard)** 点击“New Scan”,打开“Private repository”开关,并粘贴你的 access token。该 token 仅用于克隆,绝不存储。 **方式 2 — 全局 token(cron 扫描)** 在 `.env` 中设置 token,以便计划扫描能自动访问私有仓库: ``` GITHUB_TOKEN=ghp_xxxxxxxxxxxx # GitHub PAT — needs repo (read) scope GITLAB_TOKEN=glpat-xxxxxxxxxxxx # GitLab token — needs read_repository scope BITBUCKET_TOKEN=your-app-password # Bitbucket app password — needs repository (read) ``` **在哪里获取 token** - GitHub:Settings → Developer settings → Personal access tokens → Fine-grained → `Contents: Read` - GitLab:User Settings → Access Tokens → `read_repository` - Bitbucket:Personal settings → App passwords → `Repositories: Read` ## 支持的仓库 VaultScan 可扫描以下平台上的任何公共或私有仓库: - GitHub (`github.com`) - GitLab (`gitlab.com`) - Bitbucket (`bitbucket.org`) 支持的语言(通过 Semgrep + SonarQube): JavaScript、TypeScript、Python、Java、Go、PHP、Ruby、C、C++、C#、Kotlin、Swift 等等。 ## 故障排除 **SonarQube 健康检查不通过超过 5 分钟** ``` docker compose logs sonarqube | tail -20 ``` 通常是内存问题。确保 Docker Desktop 至少分配了 8 GB 内存(Settings → Resources)。 **Scanner 失败并提示“clone failed”** - 公共仓库:无需任何操作 - 私有仓库:在 `.env` 中设置 `GITHUB_TOKEN` - 找不到分支:VaultScan 会自动回退到 `master`,然后是 `main` **Dashboard 中显示“No clusters found”** 扫描已完成,但聚类尚未运行。在 Dashboard 中点击 **Re-cluster**,或者: ``` curl -X POST http://localhost:8000/recluster/your-service-name ``` **重新扫描后 Dashboard 显示陈旧数据** 点击 **Re-cluster** 以使摘要缓存失效,并使用新数据重新生成。 **端口冲突** 如果端口 3000、5000、8000 或 9000 已被占用,请编辑 `docker-compose.yml` 中的 `ports` 部分。 ## 停止和清理 ``` # 停止所有服务(保留数据) docker compose down # 停止并删除所有扫描数据 docker compose down -v # 包括镜像在内的完全清理 make clean ``` ## 贡献 1. Fork 该仓库 2. 创建一个特性分支:`git checkout -b feature/my-feature` 3. 进行修改 4. 使用 `make test-e2e` 进行测试 5. 发起一个 Pull Request 本项目的结构设计使得每个服务都可以独立部署。对 intelligence 层 的修改不需要重新构建 scanner 或 dashboard。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)
标签:Bitbucket, CWE-116, CWE-1333, CWE-353, CWE-79, CWE-95, DevSecOps, DLL 劫持, DOMPurify, Gemini AI, GitLab, GPT, LLM, React, Recharts, SAST, Semgrep, SonarQube, Syscalls, TypeScript, Unmanaged PE, WordPress安全扫描, XSS, 上游代理, 代码安全, 仪表盘, 优先级排序, 前端安全, 大语言模型, 安全债务, 安全插件, 日志审计, 根因分析, 模块化设计, 测试用例, 漏洞情报, 漏洞枚举, 漏洞管理, 漏洞聚合, 盲注攻击, 硬编码漏洞, 网络安全, 聚类分析, 自动化修复, 自动化攻击, 请求拦截, 逆向工具, 错误基检测, 隐私保护, 静态代码分析