tinydarkforge/SecGate

GitHub: tinydarkforge/SecGate

一款轻量级 CI/CD 安全门禁编排工具,将五款主流开源扫描器统一调度并输出标准化报告与退出码,在发现高危问题时自动阻断构建流水线。

Stars: 0 | Forks: 0

``` ╔═══════╗ █████ █████ █████ █████ █████ █████ █████ ║ ╔═══╗ ║ █ █ █ █ █ █ █ █ ║ ║ ⊙ ║ ║ █████ ████ █ █ ███ █████ █ ████ ║ ╚═══╝ ║ █ █ █ █ █ █ █ █ █ ╠═══════╣ █████ █████ █████ █████ █ █ █ █████ ║ ░░░░░ ║ ╔═══╬═══════╬═══╗ ━━━━━━━━━━━━━ SECURITY GATE ━━━━━━━━━━━━━ ║ ║ [===] ║ ║ Semgrep · Gitleaks · osv-scanner · Trivy ╚═══╬═══════╬═══╝ · npm audit — one command, one report, ║ ║ ║ ║ one exit code. MIT · No account · No tel. ╚═╝ ╚═╝ ```

npm license node provenance security

## ░▒▓█ 太长不看 ``` npx @tinydarkforge/secgate . ``` 对当前目录运行所有五个扫描器,输出一份 JSON 报告、一份独立的 HTML 报告,以及(可选的)SARIF 报告。检测结果干净时退出码为 `0`,存在 CRITICAL/HIGH 级别结果时退出码为 `1`。这就是本产品的全部功能。 ## ░▒▓█ 目前功能 SecGate 封装了五个现有的开源扫描器,对指定目录运行它们,并生成: - **一份统一的 JSON 报告**,汇总所有扫描器的结果 - **一份独立的 HTML 报告**,带有按扫描器区分的标签页、暗黑模式、无任何外部资源依赖 - **一份 SARIF 2.1.0 文件**,可直接上传至 GitHub Code Scanning - **一个统一的退出码** —— 当存在 CRITICAL 或 HIGH 级别的发现时为 `1`;用于阻断 CI 流水线 SecGate 并不附带自己的分析引擎。每一项发现均源于这五个底层工具之一。其核心价值在于**任务编排、结果标准化和单一退出码。** ## ░▒▓█ 扫描器 | 扫描器 | 类别 | 备注 | |---------------|---------------------------|-----------------------------------------------------------------------| | **Semgrep** | SAST (静态代码) | OSS 规则集。支持 10+ 种语言。可通过 `customSemgrepRules` 扩展。 | | **Gitleaks** | 密钥与凭证 | 工作树 + git 历史(当 `.git/` 存在时)。密钥会被脱敏。 | | **npm audit** | Node 依赖 (SCA) | 当 `package.json` 存在时运行。使用 GitHub advisory DB。 | | **osv-scanner** | 多语言 SCA | npm, PyPI, Go, Cargo, Maven, RubyGems, Packagist, NuGet, Pub. | | **Trivy** | IaC + 许可证 + 镜像 | Terraform, Kubernetes, Dockerfile, CloudFormation。基础镜像 CVE。 | 缺失的扫描器二进制文件会被**优雅地跳过**,并在报告中注明。不强制要求任何扫描器;SecGate 会使用 `$PATH` 上可用的任何工具。 ## ░▒▓█ 产品定位 SecGate **不是** SOC 平台、合规工具或漏洞管理系统。它是一个 **CI 门禁**,聚合扫描器输出并在发现严重问题时使构建失败。 | 替代方案 | 何时应选择它而非 SecGate | |--------------------|-----------------------------------------------------------------| | **Trivy standalone** | 仅扫描容器且不需要 SAST 或密钥检测。 | | **Semgrep OSS** | 仅需要带自定义规则的 SAST。 | | **Snyk** | 需要托管的漏洞库、分诊 UX、Jira 同步 —— 以及预算。| | **Aikido** | 想要 SaaS 仪表盘,并接受托管账户模式。 | **SecGate 的定位:** 零配置编排,无需账户,无遥测,仅本地输出,MIT 许可证。如果你需要 SaaS 级别的分诊或合规工作流,请购买 Snyk 或 Aikido。完整对比矩阵:[`docs/comparison.md`](docs/comparison.md)。 ## ░▒▓█ 产品愿景 SecGate 将成为更广泛安全工作流的开源输入层。**核心 CLI** —— 扫描编排、SARIF 输出、基线、抑制、HTML 报告 —— 将**永远保持 MIT 许可并免费**。未来的付费扩展可能会增加托管仪表盘、组织级策略管理、合规证据包,以及为需要比本地门禁更多功能的团队提供的多仓库聚合。这些目前尚不存在。OSS 边界定义在 [`OPEN-CORE.md`](OPEN-CORE.md) 中。 ## ░▒▓█ 前置条件 Node.js `>=18`。外部扫描器可选 —— 只需安装你想运行的工具即可。 ``` # macOS brew install semgrep gitleaks osv-scanner trivy # Linux pip install semgrep # gitleaks: https://github.com/gitleaks/gitleaks#installing # osv-scanner: https://github.com/google/osv-scanner#installation # trivy: https://aquasecurity.github.io/trivy/latest/getting-started/installation/ ``` ## ░▒▓█ 安装 ### 通过 npm 安装(推荐) ``` npm install -g @tinydarkforge/secgate ``` ### 通过 npx 一次性运行(无需安装) ``` npx @tinydarkforge/secgate . ``` ### 从源码构建 ``` git clone https://github.com/tinydarkforge/SecGate.git cd SecGate npm install chmod +x secgate.js sudo ln -sf "$(pwd)/secgate.js" /usr/local/bin/secgate ``` ## ░▒▓█ 使用方法 ``` # 扫描当前目录 (dry-run,默认) secgate . # 通过自动修复进行扫描 (仅限 npm audit fix — 请参阅以下警告) secgate . --apply # 带有调试输出的扫描 secgate . --debug # 扫描特定路径 secgate /path/to/project # 将报告写入自定义目录 (默认: 目标) secgate /path/to/project --output-dir /tmp/reports # 从报告中剥离绝对路径 (当 CI=true 时自动开启) secgate /path/to/project --strip-paths # 版本 / 帮助 secgate --version secgate --help ``` **退出码** | 代码 | 含义 | |:----:|----------------------------------------------------| | `0` | PASS —— 没有 CRITICAL 或 HIGH 级别的发现 | | `1` | FAIL —— 存在 CRITICAL 或 HIGH 级别的发现 | | `2` | 无效目标或 CLI 错误 | ## ░▒▓█ 安全 —— 在不受信任的仓库中使用 `--apply` **已到位的加固措施:** - 在 `--apply` 下执行所有 npm 命令时都会带上 `--ignore-scripts` 参数 —— 目标 `package.json`(或其依赖)中的恶意 `preinstall` / `postinstall` 脚本**不会被执行**。 - `--apply` **受限执行**:除非设置了 `SECGATE_CONFIRM_APPLY=1`(CI / 非交互模式)或用户在交互式 TTY 提示符下输入 `y`,否则拒绝运行。 - 每一次 `--apply` 执行都会被记录在报告的 `auditLog` 字段中,并附带时间戳和目标镜像输出到 stderr。 **操作指南:** - **不要在不受信任或新克隆的第三方仓库上运行 `--apply`。** 先运行 dry-run(试运行),审查结果后再做决定。 - 在 CI 中,首选 dry-run(`secgate .`)并依靠退出码来作为门禁。如果必须使用 `--apply`,请在设置了 `SECGATE_CONFIRM_APPLY=1` 的隔离临时 runner 中执行。 - 报告文件默认输出到目标目录。使用 `--output-dir` 重定向;当 `cwd !== target` 时会在 stderr 打印警告。 - 在 CI 中,会自动启用 `--strip-paths` 以防止主机路径泄露到上传的构建产物中。 ## ░▒▓█ 配置 在你的扫描目标目录下创建 `.secgate.config.json`。所有字段均为可选。 ``` { "failOn": ["critical", "high"], "scanners": { "semgrep": true, "gitleaks": true, "npm": true, "osv": true, "trivy": false }, "severityOverrides": [ { "rule": "npm-audit.lodash", "severity": "LOW" }, { "rule": "trivy-DS*", "severity": "MEDIUM" } ], "ignore": ["CVE-2024-12345", "npm:some-old-package*"], "baselineFile": ".secgate-baseline.json", "customSemgrepRules": "./rules/" } ``` JSON Schema: [`docs/config.schema.json`](docs/config.schema.json) ### 字段说明 | 字段 | 类型 | 默认值 | 描述 | |----------------------|-----------------|----------------------------|-----------------------------------------------------------------------------| | `failOn` | `string[]` | `["critical","high"]` | 导致退出码为 `1` 的严重性级别 | | `scanners` | `object` | 所有为 `true` | 将任何扫描器设置为 `false` 以跳过它 | | `severityOverrides` | `array` | `[]` | 覆盖匹配签名的严重性(支持 glob 通配符 `*`) | | `ignore` | `string[]` | `[]` | 丢弃签名匹配的发现结果(支持 glob 通配符 `*`) | | `baselineFile` | `string` | `.secgate-baseline.json` | 基线文件的路径(相对于目标目录) | | `customSemgrepRules` | `string\|null` | `null` | 传递给 semgrep 的额外 `--config=` 参数 | ### 优先级 ``` CLI flag > .secgate.config.json > built-in defaults ``` - `--baseline` 和 `--update-baseline` 仅支持通过 CLI 指定(无等效的配置项)。 - 缺失配置文件:静默处理,应用默认值。无效 JSON:记录错误,应用默认值。 ### 基线工作流 ``` # 1. 接受当前状态作为 baseline secgate . --update-baseline # 2. 在后续运行中,仅在出现全新发现时失败 secgate . --baseline ``` 将 `.secgate-baseline.json` 提交到你的代码库中。被基线化的发现结果在报告中会带有 `baseline` 标记,并被排除在失败门禁之外。 ### 内联抑制 在标记行或其紧邻的上一行添加注释: ``` // secgate:ignore db.query(userInput); db.execute(sql); // secgate:ignore my.rule.id /* secgate:ignore my.rule.id */ dangerousCall(); ``` 被抑制的发现结果不计入统计计数器。报告的 `suppressions` 部分会记录每条规则的计数以供审计。 ## ░▒▓█ CI / CD ### GitHub Actions —— 最小配置 ``` # .github/workflows/secgate.yml - name: Run SecGate run: npx @tinydarkforge/secgate . # exits 1 on CRITICAL or HIGH findings — blocks the pipeline ``` ### 非阻塞(仅生成报告) ``` - name: Run SecGate run: npx @tinydarkforge/secgate . || true - name: Upload report uses: actions/upload-artifact@v4 with: name: secgate-report path: | secgate-v7-report.json *.html ``` ### 作为复合 GitHub Action 使用 本仓库的 `.github/actions/secgate/` 目录中提供了一个复合 action。 ``` - name: SecGate Security Gate id: secgate uses: tinydarkforge/SecGate/.github/actions/secgate@main with: target: "." apply: "false" fail-on: "critical,high" format: "json,html,sarif" - name: Upload HTML + JSON if: always() uses: actions/upload-artifact@v4 with: name: secgate-report path: | secgate-v7-report.json *.html - name: Upload SARIF to Code Scanning if: always() && steps.secgate.outputs.sarif-path != '' uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ steps.secgate.outputs.sarif-path }} category: secgate ``` **Action 输入** | 输入 | 默认值 | 描述 | |-----------|------------------|----------------------------------------------------------| | `target` | `.` | 要扫描的目录 | | `apply` | `false` | 执行可修复的补救措施 | | `fail-on` | `critical,high` | 导致步骤失败的严重性级别 | | `format` | `json,html` | 输出格式 —— 以逗号分隔:`json`, `html`, `sarif`| **Action 输出** | 输出 | 描述 | |---------------|---------------------------------------------------------------| | `report-path` | `secgate-v7-report.json` 的路径 | | `sarif-path` | `.sarif.json` 的路径(仅当格式包含 SARIF 时设置) | **在生产工作流中请固定到完整的 commit SHA**: ``` uses: tinydarkforge/SecGate/.github/actions/secgate@ ``` 完整的参考工作流请参见 [`.github/workflows/example-secgate.yml`](.github/workflows/example-secgate.yml)。 ## ░▒▓█ SARIF 输出 SecGate 会与 JSON 和 HTML 并行输出 [SARIF 2.1.0](https://sarifweb.azurewebsites.net/)。SARIF 是 GitHub Code Scanning、GitLab SAST 及其他平台使用的标准格式。 ``` secgate . --format sarif # 写入: secgate-v7-report.json, .html, .sarif.json ``` `--format` 标志接受逗号分隔的列表。`sarif` 是**增量附加的** —— JSON 和 HTML 始终会被写入: ``` secgate . --format json,html,sarif # same as above secgate . --format sarif # also writes JSON + HTML ``` ### SARIF 结构 - 每个扫描器对应一个 `runs[]` 条目:`semgrep`、`gitleaks`、`npm`、`osv`、`trivy`、`trivyImage`(共 6 个)。 - 每项发现映射为一个 `result`,包含 `ruleId = signature`,`level` 由严重性派生,当存在文件/行数据时包含 `locations[].physicalLocation`。 - `properties["security-severity"]` 携带用于 GitHub 排序的 CVSS 风格分数:`CRITICAL = 9.5`、`HIGH = 7.5`、`MEDIUM = 5`、`LOW = 2`、`UNKNOWN = 0`。 ### 上传至 GitHub Code Scanning ``` - name: Run SecGate id: secgate run: npx @tinydarkforge/secgate . --format sarif - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: .sarif.json category: secgate ``` ## ░▒▓█ 报告输出 每次运行会生成: - **`secgate-v7-report.json`** —— 机器可读,schema 见下方。 - **`.html`** —— 独立的 HTML 报告,带有按扫描器区分的标签页、暗黑模式、无任何外部资源依赖。文件名由目标目录名派生。 - **`.sarif.json`** —— SARIF 2.1.0 文件(仅当传入 `--format sarif` 时生成)。 ### JSON schema ``` { "version": "0.2.3", "timestamp": "ISO 8601", "target": "/absolute/path", "mode": "dry-run | apply", "status": "PASS | FAIL", "summary": { "critical": 0, "high": 0, "medium": 0, "low": 0, "unknown": 0 }, "tools": { "semgrep": "ran | clean | skipped | error | pending", "gitleaks": "ran | clean | skipped | error | pending", "npm": "ran | clean | skipped | error | pending", "osv": "ran | clean | skipped | error | pending", "trivy": "ran | clean | skipped | error | pending", "trivyImage": "ran | clean | skipped | error | pending" }, "findings": [ { "tool": "gitleaks | semgrep | npm | osv | trivy | trivyImage", "type": "secret | code | dependency | iac | license", "severity": "CRITICAL | HIGH | MEDIUM | LOW | UNKNOWN", "signature": "rule or package ID", "message": "description", "file": "relative or absolute path, or null", "line": 42, "col": 5, "endLine": 42, "fixable": false, "fixableBy": "auto | manual | null" } ], "intelligence": { "riskScore": 0, "attackSurface": ["secret", "dependency", "iac", "license", "code"], "reasoning": [{ "issue": "...", "why": "..." }], "recommendations": ["..."] }, "remediation": { "plan": [{ "issue": "...", "patch": { "action": "...", "cmd": "display string or null", "exec": { "binary": "npm", "args": ["audit", "fix", "--ignore-scripts"], "cwd": "..." } } }], "stagedChanges": [], "executed": [], "blocked": [], "confidence": 100 }, "auditLog": [ { "timestamp": "ISO 8601", "event": "apply_start | apply_confirmed | apply_exec | apply_ok | apply_fail", "target": "target path or repo basename (if --strip-paths)" } ] } ``` ### 严重性层级 在 `addFinding()` 入口处,每一项发现都会被标准化为以下五个层级之一: | 层级 | 含义 | |-------------|------------------------------------------------------------------------------------------| | **CRITICAL**| 当前可被利用 —— 密钥、CVSS ≥ 9、硬编码凭证的 SAST 规则 | | **HIGH** | 高危影响 —— CVSS 7.0–8.9、Semgrep `ERROR`、上游评级为 `HIGH` | | **MEDIUM** | 具有实质影响 —— CVSS 4.0–6.9、`WARNING`、`MODERATE` | | **LOW** | 仅提供信息 —— CVSS < 4.0、`INFO`、`NOTE` | | **UNKNOWN** | 上游未提供严重性或提供了无法识别的值 —— 展示出来而不是错误计数 | ### 可修复性 - `fixableBy: "auto"` —— `patch()` 返回一个可执行命令;`--apply` 会运行它(目前仅支持 `npm audit fix`)。 - `fixableBy: "manual"` —— 存在补丁但需要人工干预(升级、轮换、重构)。 - `fixable: true` 是 `fixableBy === "auto"` 的镜像,用于 CI 的便捷性。 ### 工具状态 | 状态 | 含义 | |-------------|------------------------------------------------------------------------------| | `ran` | 工具已执行,存在发现结果 | | `clean` | 工具已执行无发现结果 | | `skipped` | 工具未安装,或目标不适用(无 `package.json`、无 lockfile)| | `error` | 工具生成了无法解析的输出 —— 使用 `--debug` 重新运行 | | `pending` | 工具未运行(不应出现在最终报告中) | ## ░▒▓█ 风险评分 发现结果在入口处会被应用静态权重进行评分: | 严重性 | 权重 | |----------|:------:| | CRITICAL | 10 | | HIGH | 6 | | MEDIUM | 3 | | LOW | 1 | 报告中的 `riskScore` 是所有发现结果的这些权重之和。这是一个**启发式计数值**,不是 CVSS、不是 EPSS,也不是漏洞利用概率建模。用它来对比同一仓库随时间变化的扫描结果 —— 而不是作为绝对的安全态势评分。 ## ░▒▓█ 文档 | 文档 | 包含内容 | |--------------------------------------------------------|--------------------------------------------------------------------------------| | [`OPEN-CORE.md`](OPEN-CORE.md) | OSS 核心边界与付费扩展路线图 | | [`docs/comparison.md`](docs/comparison.md) | 对比 Snyk / Trivy / Semgrep / Aikido 的功能矩阵 | | [`docs/coverage.md`](docs/coverage.md) | 扫描器到类别的矩阵及明确的盲区 | | [`docs/tuning.md`](docs/tuning.md) | 阈值、基线、抑制,CI 与本地的默认值 | | [`docs/threat-model.md`](docs/threat-model.md) | STRIDE 分析、信任边界、缓解措施 | | [`docs/adr/`](docs/adr/) | 架构决策记录 | | [`SECURITY.md`](SECURITY.md) | 漏洞报告、SLA、协调披露、供应链信任 | | [`CONTRIBUTING.md`](CONTRIBUTING.md) | 开发环境配置、分支与提交规范、PR 检查清单 | ## ░▒▓█ 贡献 参见 [`CONTRIBUTING.md`](CONTRIBUTING.md)。请按照 [`SECURITY.md`](SECURITY.md) 中的说明私下报告漏洞 —— **不要为安全报告开启公开 issue**。 ## ░▒▓█ 许可证 [MIT](LICENSE) — © TinyDarkForge ``` ╔═══╗ ║ ⊙ ║ "BLOCK. SCAN. GATE." ╚═══╝ ```
标签:AI SOC, AI推理, CISA项目, DevSecOps, Gitleaks, GNU通用公共许可证, MITM代理, Node.js, npm audit, npm包, osv-scanner, SAST, Semgrep, StruQ, Web截图, WordPress安全扫描, 上游代理, 代码安全, 依赖漏洞扫描, 安全合规, 安全网关, 容器安全, 漏洞枚举, 盲注攻击, 结构化查询, 网络代理, 自动修复, 自动化安全, 自定义脚本, 错误基检测, 静态代码分析, 风险评分