rayzhed/PWNPipe
GitHub: rayzhed/PWNPipe
一款零安装的浏览器端 GitHub Actions 静态分析器,内置 58 条检测规则,可秒级扫描任意公开仓库的 CI/CD 工作流安全风险并生成带 CVSS 评分的合规报告。
Stars: 2 | Forks: 0
# PWNPipe
GitHub Actions 静态分析器。扫描任何公共仓库的工作流文件,以查找注入向量、供应链风险和权限配置错误。
https://rayzhed.github.io/PWNPipe/
## 用例与 MVP
**目标用户:** 需要在不本地安装任何程序的情况下审计 GitHub Actions 工作流的安全工程师、DevSecOps 从业者以及开源维护者。
**用户旅程:**
- 作为一名安全工程师,我无需认证即可扫描任何公共仓库,并在 30 秒内获取风险报告,从而能够快速对 CI/CD 攻击面进行分类。
- 作为一名 DevSecOps 从业者,我通过 GitHub OAuth 登录来扫描私有仓库,并将结果导出为 SARIF,直接上传至 GitHub Security 标签页。
- 作为一名开源维护者,我对所有仓库运行批量扫描,以一目了然地揭示供应链风险并确定修复优先级。
**MVP 范围:** 检测公共仓库中影响最大的 20 种 GitHub Actions 配置错误(模板注入、未固定版本的 Actions、权限过大、硬编码密钥),并为每个发现提供 CVSS 评分和修复步骤。
除了上述内容之外的所有功能——私有仓库访问、网络信息丰富、批量扫描、多格式导出、SARIF——都是在 MVP 基础上构建的后期 MVP 层。
## 合规与报告
每个发现均包含 **CVSS v3.1 基础评分 + 向量**、**CWE ID**、适用的 **CVE 参考**、**OWASP CI/CD Security Top 10** 类别,以及检测置信度(CONFIRMED / HIGH / MEDIUM / LOW)。
综合风险评分 (0-10) 遵循 CVSS v3.1 严重性划分,并对组合攻击路径(例如:注入 + 特权触发器、供应链 + 写入权限)应用链接加成。
结果页面的导出格式:
| 格式 | 用途 |
|---|---|
| Markdown | 粘贴到渗透测试报告或审计文档中 |
| SARIF 2.1 (OASIS 标准) | 通过 `upload-sarif` action 导入到 GitHub Security 标签页 |
| JSON | 用于自定义工具或工单追踪系统的原始发现 |
| CSV | 每个发现的严重程度、CVSS、置信度、OWASP、CWE、CVE、文件、行号、描述、影响 |
| 摘要卡片 (PNG) | 包含严重性细分的风险评分可视化图 |
| 完整报告卡片 (PNG) | 以可共享图像形式展示的所有发现 |
| 打印 / PDF | 浏览器打印 — 发现项会自动展开 |
## 规则 (58)
| 规则 | OWASP | 置信度 |
|---|---|---|
| 模板注入(`run:` 中的 `${{ github.event.* }}`) | CICD-SEC-4 | HIGH |
| 危险触发器(`pull_request_target`、`workflow_dispatch`) | CICD-SEC-4 | CONFIRMED / HIGH |
| `workflow_run` 触发器滥用 | CICD-SEC-4 | CONFIRMED / HIGH |
| 未固定版本的 Actions(使用 tag 而非 SHA) | CICD-SEC-3 | CONFIRMED |
| 未固定版本的 Docker 镜像 | CICD-SEC-3 | CONFIRMED |
| 可复用工作流的 ref 未固定到 SHA | CICD-SEC-3 | CONFIRMED |
| 过大的 `permissions` | CICD-SEC-5 | HIGH / MEDIUM |
| 自托管 Runner 暴露风险 | CICD-SEC-7 | HIGH / MEDIUM |
| Artipacked(制品投毒) | CICD-SEC-6 | HIGH |
| 可绕过的机器人条件 | CICD-SEC-2 | HIGH |
| 来自不受信任输入的 `GITHUB_ENV` 写入 | CICD-SEC-4 | HIGH |
| 启用了 `ACTIONS_ALLOW_UNSECURE_COMMANDS` | CICD-SEC-7 | CONFIRMED |
| 硬编码密钥 | CICD-SEC-6 | HIGH |
| 可复用工作流上的 `secrets: inherit` | CICD-SEC-6 | HIGH / MEDIUM |
| 缓存投毒向量 | CICD-SEC-3 | MEDIUM |
| `curl \| sh` 及管道到 shell 模式 | CICD-SEC-3 | HIGH |
| 混淆的 Shell 命令 | CICD-SEC-4 | MEDIUM |
| Token 泄露到日志中 | CICD-SEC-6 | MEDIUM |
| 启用了 `ACTIONS_STEP_DEBUG` | CICD-SEC-7 | CONFIRMED |
| 不可靠的 `contains()` 授权检查 | CICD-SEC-2 | HIGH |
| 复合 `action.yml` 中的模板注入 | CICD-SEC-4 | HIGH |
| 复合 Actions 中未固定版本的 `uses:` | CICD-SEC-3 | CONFIRMED |
| 已知受 CVE 影响的 Actions(如 CVE-2025-30066) | CICD-SEC-3 | CONFIRMED |
| 在 `env:` 上下文之外展开的 Secrets | CICD-SEC-6 | HIGH |
| 步骤输出中未遮掩的 Secrets | CICD-SEC-6 | HIGH |
| `workflow_run` 制品 `GITHUB_ENV` 注入 | CICD-SEC-4 | HIGH |
| Dependabot 不安全的步骤执行 | CICD-SEC-4 | HIGH |
| Dependabot 混淆代理人绕过 | CICD-SEC-2 | HIGH |
| 硬编码的容器镜像仓库凭据 | CICD-SEC-6 | CONFIRMED |
| 工作流作用域(而非作业作用域)的 `id-token: write` | CICD-SEC-5 | HIGH / MEDIUM |
| PR 运行在自托管 Runner 上 | CICD-SEC-7 | HIGH |
| 作业环境中过度配置的 Secrets | CICD-SEC-5 | MEDIUM |
| 写入/部署工作流中缺失并发控制 | CICD-SEC-1 | MEDIUM |
| 步骤中的 `shell: cmd` / `shell: powershell` | CICD-SEC-4 | HIGH / MEDIUM |
| 缺失 Dependabot 冷却时间 (npm/pip) | CICD-SEC-3 | LOW |
| 使用长期存活的 Token 发布 PyPI/npm(应改为使用 OIDC) | CICD-SEC-6 | MEDIUM |
| 使用已归档的 Action 仓库 (网络) | CICD-SEC-3 | CONFIRMED |
| 冒名提交 - SHA 无法从规范仓库到达 (网络) | CICD-SEC-3 | CONFIRMED |
| Action ref 版本/注释不匹配 (网络) | CICD-SEC-3 | MEDIUM |
| 来自不受信任输入的 `GITHUB_OUTPUT` 写入 | CICD-SEC-4 | HIGH |
| `GITHUB_STEP_SUMMARY` Markdown 注入 | CICD-SEC-4 | HIGH |
| 由不受信任的事件数据填充的 `strategy.matrix` | CICD-SEC-4 | HIGH |
| 由不受信任的输入控制的 `runs-on` 标签 | CICD-SEC-7 | CONFIRMED / HIGH |
| 作业缺少 `timeout-minutes` (DoS / 成本) | CICD-SEC-7 | MEDIUM |
| `continue-on-error: true` 掩盖了安全故障 | CICD-SEC-10 | HIGH / MEDIUM |
| Renovate 自动合并 / 升级后命令 / 直接推送 | CICD-SEC-3 | CONFIRMED |
| Pre-commit 钩子未固定到 SHA / `language: system` | CICD-SEC-3 | HIGH |
| 默认分支上禁用了分支保护 (网络) | CICD-SEC-2 | CONFIRMED |
| 禁用了 GitHub Secret Scanning (网络) | CICD-SEC-10 | CONFIRMED |
| 禁用了 Secret Scanning Push Protection (网络) | CICD-SEC-10 | CONFIRMED |
| `if:` 条件始终为 true(混合了 `${{ }}` + 外部的比较运算符) | CICD-SEC-2 | CONFIRMED |
| `issue_comment` / PR 审查 TOCTOU - 可变的 checkout ref | CICD-SEC-4 | CONFIRMED |
| 禁用了撤销的 GitHub App token (`skip-token-revoke: true`) | CICD-SEC-6 | CONFIRMED |
| 带有聚合风险表的多仓库批量扫描 | - | - |
## 架构
```
Browser (React + Vite)
|- GitHub API fetch workflow files, user info
\- Cloudflare Worker OAuth code exchange (keeps client_secret off the client)
```
分析完全在浏览器中运行。不会将任何扫描数据发送到任何地方。
## 技术选型
**React 18 + Vite** — React 的组件模型清晰地映射到多阶段 UI(登录 → 扫描 → 结果)。Vite 提供了亚秒级的 HMR,并将 58 条规则的引擎进行 Tree-shaking 优化为精简的生产包。使用原生 JS 方法将需要从头开始重新实现状态管理;而更重的元框架(Next.js、Remix)会增加服务器端基础架构需求,这与经过深思熟虑的无服务器、隐私优先的设计相冲突。
**Tailwind CSS + Radix UI** — Tailwind 通过 CSS 变量提供一致的暗黑模式设计系统,无运行时开销,保持了包的体积小巧。Radix UI 处理发现卡片的无障碍折叠/展开模式(键盘导航、ARIA 属性),否则这些将需要大量的手动 ARIA 工作。
**Cloudflare Workers** — OAuth `client_secret` 绝不能暴露给浏览器。Cloudflare Worker 是最小可行的后端:一个没有持久状态的单个边缘函数,零冷启动延迟,并且其免费额度足以应对预期的流量。替代方案(Netlify Functions、Vercel Serverless)同样有效;选择 Cloudflare 是因为其 `wrangler` 的开发者体验以及通过 `wrangler secret put` 实现的内置密钥管理。
**GitHub Pages** — 与零服务器架构相匹配的静态托管。免费包含 HTTPS 和全球 CDN。SPA 路由限制(GitHub Pages 没有动态路由)通过 `public/404.html` 中已有的标准 404 → `index.html` 重定向来解决。
## 本地开发
```
npm install
npm run dev # http://localhost:5173/PWNPipe/
```
将 `VITE_DEV_TOKEN=ghp_...` 添加到 `.env.local` 中,以便在开发时跳过 OAuth 流程。
## 自托管
**1. GitHub OAuth App** - 将回调 URL 设置为 `https://YOUR_USERNAME.github.io/PWNPipe/`,并将客户端 ID 复制到 `src/config.js` 中。
**2. Cloudflare Worker**
```
cd worker
npx wrangler secret put GITHUB_CLIENT_ID
npx wrangler secret put GITHUB_CLIENT_SECRET
npx wrangler secret put ALLOWED_ORIGIN # https://YOUR_USERNAME.github.io
npx wrangler deploy
```
使用部署好的 Worker URL 更新 `src/config.js` 中的 `WORKER_URL`。
**3. GitHub Pages** - 推送到 `main`,包含的工作流将处理构建和部署。
## URL 方案
```
/PWNPipe/owner/repo scans the repo on load
/PWNPipe/ scan input
```
标签:CI/CD安全, CVSS评分, DevSecOps, GitHub Actions, GitHub OAuth, Llama, OWASP Top 10, pwn请求, SARIF, SAST, StruQ, 上游代理, 代码安全, 合规报告, 攻击面分析, 数据展示, 漏洞枚举, 盲注攻击, 程序员工具, 红队, 网络安全, 自动笔记, 自定义脚本, 软件开发工具包, 错误基检测, 隐私保护, 静态代码分析