raghu-py/securedev-action

GitHub: raghu-py/securedev-action

SecureDev Action 是一个GitHub Action,用于在CI/CD中自动扫描代码安全风险并生成报告,帮助开发者早期发现漏洞。

Stars: 0 | Forks: 0

# SecureDev 行动 **一个独立的 Docker GitHub Action,用于扫描代码和配置文件的安全风险。** 由 **Raghu Soni** 构建
![GitHub Actions](https://img.shields.io/badge/GitHub-Actions-2088FF?style=for-the-badge&logo=githubactions&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-Action-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![Python](https://img.shields.io/badge/Python-Security%20Scanner-3776AB?style=for-the-badge&logo=python&logoColor=white) ![SARIF](https://img.shields.io/badge/SARIF-Compatible-6f42c1?style=for-the-badge)
[概述](#overview) · [使用方法](#usage) · [输入参数](#inputs) · [输出参数](#outputs) · [规则](#security-rules) · [本地开发](#local-development) · [常见问题](#faq)
## 概述 **SecureDev Action** 是一个轻量级、独立的 GitHub Actions 安全扫描器。 它扫描源代码、脚本、Docker 文件、基础设施文件、配置文件以及基于文本的项目文件,检测常见安全问题,例如: - 硬编码密钥 - 危险的命令执行 - SQL 注入模式 - 不安全的反序列化 - 弱加密 - 不安全的 Docker 配置 - 高风险的 Kubernetes 设置 - 不安全的 GitHub Actions 用法 - 调试和不安全的配置值 ## 主要特性 | 特性 | 描述 | |---|---| | Docker Action | 在 Docker 容器内运行 | | 独立 | 不依赖外部扫描服务 | | 多语言扫描 | 支持 Python, JavaScript, PHP, Ruby, Java, Go, shell, 配置, Docker, Kubernetes, IaC 等 | | 默认仅严重级别失败 | 仅当检测到严重发现时,CI 才会失败 | | JSON 输出 | 生成机器可读报告 | | SARIF 输出 | 生成供安全工具使用的 SARIF 报告 | | Markdown 输出 | 生成可读的安全摘要 | | GitHub 注解 | 在 GitHub Actions 日志中显示发现 | | 无 PR 评论 | 不在拉取请求上发布评论 | | 可配置扫描 | 支持包含、排除、文件大小、输出格式和严重性阈值等选项 | ## 使用方法 创建工作流文件: ``` name: SecureDev Scan on: push: branches: - main pull_request: permissions: contents: read jobs: securedev: name: SecureDev Security Scan runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run SecureDev Action uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" output-format: "all" output-dir: "securedev-results" ``` 在创建发布标签之前进行测试,可以使用: ``` uses: raghu-py/securedev-action@main ``` 对于稳定使用,创建一个发布标签如 `v1` 并使用: ``` uses: raghu-py/securedev-action@v1 ``` ## 输入参数 | 输入参数 | 必需 | 默认值 | 描述 | |---|---:|---|---| | `path` | 否 | `.` | 要扫描的路径。使用 `.` 表示检出的仓库根目录。 | | `fail-on` | 否 | `critical` | 导致操作失败的最低严重性。允许的值:`critical`, `high`, `medium`, `low`, `none`。 | | `output-dir` | 否 | `securedev-results` | 写入 JSON, SARIF 和 Markdown 报告的目录。 | | `output-format` | 否 | `all` | 要生成的报告格式。允许的值:`all`, `json`, `sarif`, `markdown`, `md`,或用逗号分隔的值如 `json,sarif`。 | | `include` | 否 | 空 | 要包含的逗号分隔的 glob 模式。空表示 `path` 下的所有文件。 | | `exclude` | 否 | 空 | 除了内置默认值外,要排除的逗号分隔的 glob 模式。 | | `max-file-size-kb` | 否 | `1024` | 要扫描的最大文件大小,单位为 KB。 | | `show-snippets` | 否 | `true` | 在报告中包含匹配的源代码片段。允许的值:`true`, `false`。 | | `annotations` | 否 | `true` | 为发现创建 GitHub 工作流注解。这不会发布 PR 评论。 | ## 输出参数 | 输出参数 | 描述 | |---|---| | `result` | 最终结果:`pass` 或 `fail`。 | | `findings_count` | 发现总数。 | | `critical_count` | 严重发现数量。 | | `high_count` | 高危发现数量。 | | `medium_count` | 中危发现数量。 | | `low_count` | 低危发现数量。 | | `report_json` | JSON 报告路径(生成时)。 | | `report_sarif` | SARIF 报告路径(生成时)。 | | `report_markdown` | Markdown 报告路径(生成时)。 | 输出使用示例: ``` - name: Run SecureDev Action id: securedev uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" - name: Print result if: always() run: | echo "Result: ${{ steps.securedev.outputs.result }}" echo "Findings: ${{ steps.securedev.outputs.findings_count }}" echo "Critical: ${{ steps.securedev.outputs.critical_count }}" ``` ## 生成报告 默认情况下,报告写入到: ``` securedev-results/ ``` 生成的报告文件: | 文件 | 格式 | 用途 | |---|---|---| | `securedev-report.json` | JSON | 完整的机器可读安全报告 | | `securedev-report.sarif` | SARIF | 供安全工具使用的静态分析报告 | | `securedev-summary.md` | Markdown | 人类可读的扫描摘要 | 示例: ``` securedev-results/ ├── securedev-report.json ├── securedev-report.sarif └── securedev-summary.md ``` ## 上传报告作为工件 ``` name: SecureDev Scan on: push: pull_request: permissions: contents: read jobs: scan: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Run SecureDev Action uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" output-format: "all" output-dir: "securedev-results" - name: Upload SecureDev reports if: always() uses: actions/upload-artifact@v4 with: name: securedev-results path: securedev-results/ ``` ## 上传 SARIF 到 GitHub Code Scanning SecureDev Action 生成 SARIF 报告。要将其上传到 GitHub Code Scanning,请添加一个 SARIF 上传步骤。 ``` name: SecureDev Code Scanning on: push: branches: - main pull_request: permissions: contents: read security-events: write jobs: securedev: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Run SecureDev Action uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" output-format: "sarif" output-dir: "securedev-results" - name: Upload SARIF if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: securedev-results/securedev-report.sarif ``` ## 严重性级别 | 严重性 | 含义 | 默认是否导致 CI 失败 | |---|---|---:| | `critical` | 高度危险的问题,应立即修复 | 是 | | `high` | 严重的安全问题 | 否 | | `medium` | 需要审查的风险模式 | 否 | | `low` | 弱点或加固建议 | 否 | | `info` | 信息性发现 | 否 | 默认行为: ``` fail-on = critical ``` 这意味着仅当检测到至少一个严重发现时,操作才会失败。 ## 失败模式 | `fail-on` 值 | 工作流在何时失败 | |---|---| | `critical` | 严重发现 | | `high` | 严重和高危发现 | | `medium` | 严重、高危和中危发现 | | `low` | 严重、高危、中危和低危发现 | | `none` | 永不因发现而失败 | 示例: ``` with: fail-on: "none" ``` ## 安全规则 SecureDev Action 包含多个类别的规则。 | 规则 ID | 名称 | 严重性 | 类别 | |---|---|---|---| | `SEC001` | AWS 访问密钥暴露 | `critical` | 密钥 | | `SEC002` | GitHub 令牌暴露 | `critical` | 密钥 | | `SEC003` | 私钥材料被提交 | `critical` | 密钥 | | `SEC004` | Google API 密钥暴露 | `critical` | 密钥 | | `SEC005` | Stripe 生产环境密钥暴露 | `critical` | 密钥 | | `SEC006` | Slack 令牌暴露 | `critical` | 密钥 | | `SEC007` | 通用硬编码密钥 | `high` | 密钥 | | `PY001` | 使用 Python `eval` | `high` | 注入 | | `PY002` | 使用 Python `exec` | `high` | 注入 | | `PY003` | Shell 命令执行 | `high` | 命令注入 | | `PY004` | `subprocess` 配合 `shell=True` | `critical` | 命令注入 | | `PY005` | 不安全的 pickle 反序列化 | `high` | 反序列化 | | `PY006` | 不安全的 YAML 加载 | `high` | 反序列化 | | `PY007` | TLS 证书验证被禁用 | `high` | 传输安全 | | `PY008` | 启用调试模式 | `high` | 配置 | | `PY009` | SQL 查询使用字符串格式化构建 | `critical` | SQL 注入 | | `PY010` | 弱哈希算法 | `medium` | 加密 | | `PY011` | 弱或高风险的加密模式 | `high` | 加密 | | `PY012` | JWT 签名验证被禁用 | `critical` | 认证 | | `JS001` | 使用 JavaScript `eval` | `high` | 注入 | | `JS002` | HTML 注入点 | `high` | XSS | | `JS003` | 使用 React `dangerouslySetInnerHTML` | `high` | XSS | | `JS004` | Node 命令执行 | `high` | 命令注入 | | `JS005` | Node 中 TLS 证书验证被禁用 | `high` | 传输安全 | | `WEB001` | 检测到内联脚本 | `low` | XSS 加固 | | `PHP001` | 使用 PHP `eval` | `critical` | 注入 | | `PHP002` | PHP 不安全反序列化 | `high` | 反序列化 | | `PHP003` | 可能的 PHP SQL 注入 | `critical` | SQL 注入 | | `RB001` | Ruby 不安全 YAML 加载 | `high` | 反序列化 | | `RB002` | Ruby 命令执行 | `high` | 命令注入 | | `JAVA001` | Java 命令执行 | `high` | 命令注入 | | `GO001` | Go 命令执行 | `high` | 命令注入 | | `CFG001` | CORS 通配符来源 | `high` | 配置 | | `CFG002` | 不安全的调试配置 | `high` | 配置 | | `CFG003` | SSH root 登录已启用 | `high` | 配置 | | `CFG004` | SSH 密码认证已启用 | `medium` | 配置 | | `DOCKER001` | Docker 镜像使用 latest 标签 | `medium` | 供应链 | | `DOCKER002` | Docker `ADD` 从远程 URL 获取 | `medium` | 供应链 | | `DOCKER003` | 配置了特权容器 | `critical` | 容器安全 | | `K8S001` | Kubernetes 特权容器 | `critical` | 容器安全 | | `K8S002` | Kubernetes 启用了主机网络 | `high` | 容器安全 | | `K8S003` | Kubernetes 启用了特权提升 | `high` | 容器安全 | | `IAC001` | 公开的 SSH 入口 | `critical` | 云安全 | | `IAC002` | 公开的对象存储 ACL | `critical` | 云安全 | | `GHA001` | GitHub Action 固定到可变 ref | `medium` | 供应链 | | `GEN001` | 过于宽松的文件权限 | `high` | 配置 | | `JWT001` | 接受 JWT none 算法 | `critical` | 认证 | | `SQL001` | 可能的 SQL 注入模式 | `critical` | SQL 注入 | ## 扫描流程 ``` flowchart TD A[GitHub workflow starts] --> B[Checkout repository] B --> C[Run SecureDev Docker Action] C --> D[Resolve scan path] D --> E[Walk files] E --> F[Skip binary, large, generated, and excluded files] F --> G[Apply security rules] G --> H[Create findings] H --> I[Generate JSON, SARIF, and Markdown reports] I --> J[Emit GitHub annotations] J --> K{Findings meet fail-on threshold?} K -->|Yes| L[Fail workflow] K -->|No| M[Pass workflow] ``` ## 项目结构 ``` securedev-action/ ├── action.yml ├── Dockerfile ├── entrypoint.sh ├── .gitignore ├── .dockerignore ├── securedev_action/ │ ├── __init__.py │ ├── __main__.py │ ├── cli.py │ ├── config.py │ ├── filewalker.py │ ├── models.py │ ├── reporters.py │ ├── rules.py │ └── scanner.py └── tests/ └── test_scanner.py ``` ## 文件和文件夹排除 扫描器会跳过常见的生成文件、依赖项、缓存、二进制文件、存档、媒体和锁文件。 ### 内置排除的文件夹 ``` .git/ .hg/ .svn/ .idea/ .vscode/ .tox/ .nox/ .venv/ venv/ env/ node_modules/ bower_components/ vendor/ dist/ build/ target/ out/ coverage/ htmlcov/ __pycache__/ .pytest_cache/ .mypy_cache/ .ruff_cache/ .next/ .nuxt/ .turbo/ .cache/ tmp/ temp/ logs/ ``` ### 内置排除的文件模式 ``` *.png *.jpg *.jpeg *.gif *.webp *.ico *.pdf *.zip *.tar *.tar.gz *.tgz *.rar *.7z *.gz *.bz2 *.xz *.mp4 *.mov *.mp3 *.wav *.woff *.woff2 *.ttf *.otf *.eot *.lock package-lock.json pnpm-lock.yaml yarn.lock poetry.lock Pipfile.lock Cargo.lock Gemfile.lock composer.lock ``` ## 包含和排除示例 仅扫描 Python 文件: ``` with: path: "." include: "**/*.py" ``` 扫描 Python 和 JavaScript 文件: ``` with: path: "." include: "**/*.py,**/*.js,**/*.ts" ``` 排除测试和文档文件夹: ``` with: path: "." exclude: "tests/**,docs/**" ``` 将最大文件大小增加到 2 MB: ``` with: max-file-size-kb: "2048" ``` 禁用报告中的代码片段: ``` with: show-snippets: "false" ``` 禁用 GitHub 注解: ``` with: annotations: "false" ``` ## GitHub 注解 当启用 `annotations` 时,SecureDev Action 会打印与 GitHub 兼容的工作流注解。 示例: ``` ::error file=app/main.py,line=20,col=1,title=PY004: subprocess with shell=True::subprocess is called with shell=True, which can allow command injection. ``` 这些注解会出现在 GitHub Actions 日志中。 重要提示: ## 本地开发 克隆仓库: ``` git clone https://github.com/raghu-py/securedev-action.git cd securedev-action ``` 本地运行扫描器: ``` python -m securedev_action.cli --path . --fail-on critical --output-format all ``` 也可以通过包入口点运行: ``` python -m securedev_action --path . --fail-on critical --output-format all ``` 运行测试: ``` python -m pytest tests ``` 构建 Docker 镜像: ``` docker build -t securedev-action . ``` 本地运行 Docker 镜像: ``` docker run --rm -v "$PWD:/workspace" securedev-action --path /workspace --fail-on critical ``` 检查版本: ``` python -m securedev_action --version ``` ## 发现示例 ### 硬编码的 GitHub 令牌 ``` GITHUB_TOKEN = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` 预期发现: ``` SEC002: GitHub token exposed Severity: critical ``` ### 危险的 Python subprocess 用法 ``` import subprocess subprocess.run(user_input, shell=True) ``` 预期发现: ``` PY004: subprocess with shell=True Severity: critical ``` ### SQL 注入模式 ``` query = "SELECT * FROM users WHERE id = " + user_id ``` 预期发现: ``` SQL001: Possible SQL injection pattern Severity: critical ``` ### 弱哈希算法 ``` import hashlib password_hash = hashlib.md5(password.encode()).hexdigest() ``` 预期发现: ``` PY010: Weak hash algorithm Severity: medium ``` ## 抑制发现 扫描器识别常见的抑制标记。 仅当您手动审查了发现并确认其安全时,才使用抑制。 支持的标记包括: ``` securedev: ignore securedev-ignore pragma: allowlist secret nosec ``` 示例: ``` example_token = "not-a-real-token" # securedev: ignore ``` ## 推荐工作流 ``` name: Security on: pull_request: push: branches: - main permissions: contents: read jobs: securedev: name: SecureDev runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Scan repository uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" output-format: "all" output-dir: "securedev-results" - name: Upload reports if: always() uses: actions/upload-artifact@v4 with: name: securedev-results path: securedev-results/ ``` ## 高级工作流 此工作流扫描源文件、生成报告、将其作为工件上传,并将 SARIF 上传到 GitHub Code Scanning。 ``` name: Advanced SecureDev Scan on: push: branches: - main pull_request: permissions: contents: read security-events: write jobs: securedev: name: SecureDev Advanced Scan runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Run SecureDev Action uses: raghu-py/securedev-action@v1 with: path: "." fail-on: "critical" output-format: "all" output-dir: "securedev-results" exclude: "tests/fixtures/**,docs/examples/**" max-file-size-kb: "1024" show-snippets: "true" annotations: "true" - name: Upload SecureDev reports if: always() uses: actions/upload-artifact@v4 with: name: securedev-results path: securedev-results/ - name: Upload SARIF if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: securedev-results/securedev-report.sarif ``` ## JSON 报告示例 ``` { "tool": { "name": "SecureDev Action", "version": "1.0.0", "author": "Raghu Soni" }, "summary": { "scanned_files": 25, "skipped_files": 4, "findings_count": 2, "counts_by_severity": { "critical": 1, "high": 1, "medium": 0, "low": 0, "info": 0 } }, "findings": [ { "rule_id": "PY004", "title": "subprocess with shell=True", "severity": "critical", "file_path": "app/runner.py", "line": 14 } ] } ``` ## Markdown 报告示例 ``` # SecureDev 安全扫描 **Status:** FAIL ## 摘要 | Metric | Value | |---|---:| | Scanned files | 25 | | Skipped files | 4 | | Total findings | 2 | | Critical | 1 | | High | 1 | | Medium | 0 | | Low | 0 | | Info | 0 | ``` ## 何时使用此 Action SecureDev Action 适用于: - 开源仓库 - Python 项目 - JavaScript 和 TypeScript 项目 - 基于 Docker 的应用程序 - DevSecOps 学习 - CI 中的安全检查 - 拉取请求安全检查 - 轻量级静态分析 ## 此 Action 不是什么 SecureDev Action 不能完全替代: - 手动安全审查 - 专业的 SAST 平台 - 依赖项漏洞扫描器 - 运行时安全测试 - 渗透测试 - 支持完整 Git 历史记录的密钥扫描 它旨在早期捕获常见的风险模式。 ## 安全理念 1. 保持安全检查易于理解。 2. 避免将有用信息隐藏在复杂的工具背后。 3. 使报告对开发者可读。 4. 默认仅在严重发现时才使 CI 失败。 5. 偏好实际检测而非嘈杂的输出。 ## 维护者检查清单 在创建新版本之前: - [ ] 本地运行测试 - [ ] 本地构建 Docker 镜像 - [ ] 在示例仓库上测试 Action - [ ] 验证 JSON 报告生成 - [ ] 验证 SARIF 报告生成 - [ ] 验证 Markdown 报告生成 - [ ] 确认 `fail-on: critical` 行为 - [ ] 创建版本标签如 `v1.0.0` - [ ] 移动或更新主要标签如 `v1` ## 发布标签 推荐的标签: | 标签 | 用途 | |---|---| | `v1.0.0` | 确切的发布版本 | | `v1` | 稳定的主要版本 | | `main` | 开发版本 | 创建发布标签: ``` git tag v1.0.0 git push origin v1.0.0 ``` 创建或更新主要标签: ``` git tag -f v1 v1.0.0 git push origin v1 --force ``` 推荐的用户语法: ``` uses: raghu-py/securedev-action@v1 ``` ## 详细说明
SecureDev Action 如何决定是否失败? SecureDev Action 将所有发现与配置的 `fail-on` 严重性进行比较。 例如: ``` with: fail-on: "critical" ``` 这仅在存在至少一个严重发现时失败。 如果扫描发现高危、中危或低危发现但没有严重发现,则工作流通过。
SecureDev Action 是否发布 PR 评论? 否。 此 Action 不发布拉取请求评论。 它通过以下方式报告发现: - GitHub Actions 日志 - GitHub 工作流注解 - JSON 报告 - SARIF 报告 - Markdown 摘要
我可以禁用工作流注解吗? 可以。 ``` with: annotations: "false" ```
我能否阻止 Action 使 CI 失败? 可以。 ``` with: fail-on: "none" ``` 这仍然会生成报告,但发现不会使工作流失败。
这是否扫描二进制文件? 否。 二进制文件会自动跳过。扫描器专注于可能包含代码、配置、密钥或基础设施定义的文本文件。
## 审查键盘快捷键 在 GitHub 中审查发现时: | 操作 | 快捷键 | |---|---| | 搜索仓库 | t | | 打开命令面板 | Ctrl + K | | 在浏览器页面中搜索 | Ctrl + F | | 在 macOS 浏览器页面中搜索 | Cmd + F | ## 故障排除 | 问题 | 可能原因 | 解决方法 | |---|---|---| | 未扫描文件 | `path` 输入错误 | 使用 `path: "."` | | 报告缺失 | `output-format` 值错误 | 使用 `output-format: "all"` | | 工作流失败 | 检测到严重发现 | 审查生成的报告 | | SARIF 上传失败 | 缺少权限 | 添加 `security-events: write` | | 跳过的文件过多 | 文件大小或排除规则 | 检查 `max-file-size-kb` 和 `exclude` | | 未显示注解 | 注解被禁用 | 设置 `annotations: "true"` | ## 常见问题 ### SecureDev Action 是独立的吗? 是的。它作为 Docker GitHub Action 运行,不需要外部 API。 ### 它会将我的代码发送到任何地方吗? 不会。扫描器在 GitHub Actions 环境内运行。 ### 它扫描私有仓库吗? 是的。它可以扫描安装并允许运行工作流的任何仓库。 ### 它是否替代专业安全工具? 否。它是一个用于常见风险模式的轻量级扫描器。将其与其他安全工具和手动审查一起使用。 ### 它是否扫描 Git 历史记录? 否。它扫描检出的工作树。 ### 它支持 SARIF 吗? 是的。它可以生成: ``` securedev-results/securedev-report.sarif ``` ### 它支持 Markdown 报告吗? 是的。它可以生成: ``` securedev-results/securedev-summary.md ``` ## 贡献 欢迎贡献。 好的贡献包括: - 新的安全规则 - 更好的误报处理 - 更多的测试用例 - 改进的 SARIF 输出 - 更好的文档 - 新的示例 - 更清晰的报告 在提交拉取请求之前: 1. 保持代码可读。 2. 添加或更新测试。 3. 避免嘈杂的规则。 4. 使发现可操作。 5. 运行测试套件。 ``` python -m pytest tests ``` ## 作者
Raghu Soni
Raghu Soni

Python Developer and Cybersecurity Learner
## 免责声明 SecureDev Action 是一个轻量级的静态安全扫描器。 它可能产生: - 误报 - 漏报 - 受上下文限制的发现 - 遗漏的漏洞 在做出安全决策之前,请始终手动审查发现。 ## 使用的 Markdown 特性 此 README 使用: - 标题 - 表格 - 徽章 - 链接 - 引用 - 有序列表 - 无序列表 - 任务列表 - 代码块 - 行内代码 - HTML 对齐 - 可折叠的详情部分 - Mermaid 图表 - 键盘标签 - 脚注
**SecureDev Action** 使用 Python, Docker, 和 GitHub Actions 构建。
[^sarif]: SARIF 表示静态分析结果交换格式 (Static Analysis Results Interchange Format)。 [^sast]: SAST 表示静态应用程序安全测试 (Static Application Security Testing)。 [^ci]: CI 表示持续集成 (Continuous Integration)。
标签:Chrome Headless, CI/CD安全, DevSecOps, Docker Action, GitHub Actions, IaC安全, IPv6支持, Kubernetes安全, Llama, SARIF报告, SQL注入检测, Web截图, 上游代理, 代码安全分析, 多语言支持, 安全扫描, 安全测试框架, 安全风险评估, 容器安全, 密钥泄露检测, 开源框架, 弱加密检测, 持续集成, 时序注入, 脚本安全, 自动笔记, 请求拦截, 逆向工具, 配置文件安全