jeffersongoncalves/secure-lock-cli

GitHub: jeffersongoncalves/secure-lock-cli

安全锁命令行工具,用于审计依赖项漏洞并判断更新安全性。

Stars: 1 | Forks: 0

![Secure Lock CLI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/e4fb75ce98093429.png)
# 安全锁命令行工具 `secure-lock` 对项目的依赖项进行审计,并为每个包回答三个问题: 1. **是否有更新的版本?**(注册表查找) 2. **安装的版本是否存在漏洞?**(咨询数据库查找) 3. **可用的更新实际上是否安全?** — 即目标版本是否真的离开了漏洞范围,而不仅仅是更新? 该工具源于最近一波供应链攻击(Composer 和 npm 上的受损害/漏洞包),它将 *有用的升级,修复了漏洞* 与 *无用的升级,仍然暴露* 区分开来。 它涵盖了 **Composer** (`composer.lock`) 和共享 npm 生态系统的 JavaScript 管理器:**npm** (`package-lock.json` v1/v2/v3 和 `npm-shrinkwrap.json`),**pnpm** (`pnpm-lock.yaml` lockfileVersion 5/6/9),**bun** (`bun.lock` 文本锁文件) 和 **yarn** (`yarn.lock` 经典 v1 和 berry v2+)。`ECO` 列显示了包来源的实际管理器,而咨询和建议与共享 npm 生态系统进行解析。 使用 [Laravel Zero](https://laravel-zero.com) 构建,并模仿了此 monorepo 中的其他 CLIs。 ![secure-lock audit](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/384b9412a7093430.png) 每个包都会与注册表和 GitHub 咨询数据库进行核对,然后进行分类 — 这里六个包已发布修复(`SAFE`),一个只有更新的版本(`UPDATE`)。 ## 要求 - PHP `^8.2` - 一个 `composer.lock` 和/或一个 `package-lock.json` 以进行审计 - 可选的 `GITHUB_TOKEN`(将 GitHub 咨询 API 速率限制从 ~60 req/h 提高到 5000 req/h) ## 安装 ### 全局(推荐) ``` composer global require jeffersongoncalves/secure-lock-cli ``` 只要 Composer 的全局 `vendor/bin` 在其中,二进制 `secure-lock` 就会在您的 `PATH` 上。 ### 从源 ``` git clone https://github.com/jeffersongoncalves/secure-lock-cli.git cd secure-lock-cli composer install ``` ## 使用 ``` secure-lock # audit the current project (default command) secure-lock --only-vuln # only show packages at risk secure-lock --no-dev # ignore dev dependencies secure-lock --json > audit.json # structured output for CI secure-lock --dir=/path/to/proj # audit a specific directory secure-lock --fix # also print upgrade commands ``` JavaScript 锁文件会根据优先级自动检测在项目目录中(`pnpm` > `bun` > `yarn` > `npm`);通过传递 `--pnpm`/`--bun`/`--yarn`/`--npm` 来显式指定一个。 ### 选项 ``` --dir= Project directory (defaults to the current directory) --composer= Explicit path to composer.lock --npm= Explicit path to package-lock.json --pnpm= Explicit path to pnpm-lock.yaml --bun= Explicit path to bun.lock --yarn= Explicit path to yarn.lock --only-vuln Show only packages at risk --fix Print upgrade commands that leave every vulnerable range --no-dev Ignore development dependencies --ignore= Advisory id (GHSA or CVE) to suppress; repeatable --config= Path to a secure-lock.json (auto-detected otherwise) --fail-on-unverified Exit non-zero when an advisory lookup fails --no-packagist Disable the Packagist advisory fallback for Composer --no-npm-audit Disable the npm audit advisory fallback for JS --json Structured JSON output (for CI) --sarif SARIF 2.1.0 output (for GitHub code scanning) --github-token= GitHub token (or the GITHUB_TOKEN env var) --cache-ttl=3600 HTTP cache TTL in seconds (0 disables caching) ``` ## 判决 对于每个包,该工具会将针对 **当前** 版本的咨询与仍然针对 **最新** 版本的咨询进行比较: | 判决 | 徽章 | 意义 | |---------|-------|---------| | `VULN` | `● VULN` (红色) | 现在存在漏洞,没有发布的修复 | | `RISKY_UPDATE` | `● RISKY` (洋红色) | 存在更新但仍然暴露 | | `UNKNOWN` | `● UNKNOWN` (黄色) | 咨询查找失败 — 状态未验证 | | `SAFE_UPDATE` | `● SAFE` (绿色) | 更新 **修复** 漏洞 | | `UPDATE` | `● UPDATE` (青色) | 更新版本,没有已知漏洞 | | `OK` | `● OK` (灰色) | 最新且干净 | 该表按风险排序(`VULN` > `RISKY` > `UNKNOWN` > `SAFE` > `UPDATE` > `OK`),而 `NOTE` 列显示最高严重性的咨询为 `SEVERITY CVE-XXXX (+N)`(如果存在,则为 CVE,否则为 GHSA id)。 ## 修复 通过传递 `--fix` 来打印每个当前存在漏洞的包的每个管理器的升级命令。目标是大于已安装版本的最小 **安全** 版本,而不是最新的版本,这样升级是最小的且经过验证的 — 而不仅仅是“最新的”: ![secure-lock audit --fix](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/1a99d1a657093431.png) 注意目标是最小的安全版本,而不是最新的: `guzzlehttp/guzzle` 升级到 `6.5.8`(不是 `7.10.5`),而 `phpunit` 升级到 `9.6.33`。 **直接与间接。** 直接依赖项会得到一个简单的 `add`/`require`/`install`。一个 *间接* 依赖项不能以这种方式固定 — 一个 `npm install` 不会达到嵌套版本 — 因此建议使用管理器的覆盖机制:`overrides`(npm/bun)、`pnpm.overrides`(pnpm)或 `resolutions`(yarn)在 `package.json` 中。Composer 总是使用 `composer require`,这也固定了间接包。 没有版本可以离开漏洞范围的包(`VULN`)将被跳过。 在 `--json` 模式下,每个包都会获得一个 `fix` 对象(`{target, command, transitive}`)或 `null`。 ## 抑制咨询 否则,已接受或无法修复的风险将永远使 CI 失败。传递一个或多个 `--ignore` 标志,或将 `secure-lock.json` 提交到项目根目录(自动检测,或使用 `--config` 指向它): ``` { "ignore": [ "CVE-2022-31091", { "id": "GHSA-xxxx-yyyy-zzzz", "expires": "2026-12-31" } ] } ``` ``` secure-lock --ignore=GHSA-xxxx-yyyy-zzzz --ignore=CVE-2022-31091 ``` 被忽略的咨询不再计入判决。带有 `expires` 日期的条目在日期过后停止抑制,因此延迟的风险会重新出现而不是被遗忘。 ## GitHub 代码扫描(SARIF) `--sarif` 输出 SARIF 2.1.0,GitHub 可以将其导入以在存储库的 **Security › Code scanning** 选项卡中显示结果: ``` name: secure-lock on: [push, pull_request] permissions: security-events: write jobs: audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - run: composer global require jeffersongoncalves/secure-lock-cli - run: secure-lock --no-dev --sarif > results.sarif env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} continue-on-error: true - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif ``` ## 退出代码(用于 CI) - `0` — 没有关键风险。 - `1` — 找到 `VULN` 或 `RISKY_UPDATE`(使管道失败)。 - `2` — 输入错误(找不到锁文件、无效的 JSON 等)。 ### GitHub 动作 ``` - run: secure-lock --no-dev env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` ## 工作原理 - **注册表** — Composer:`repo.packagist.org/p2/{name}.json`,遍历每个版本并忽略预发布版本(`alpha|beta|rc|dev|next|canary|nightly`)以找到最高的稳定版本。npm:`registry.npmjs.org/{name}`(`/` 编码为 `%2F` 以用于范围包),使用 `dist-tags.latest`。 - **咨询** — GitHub 咨询数据库 REST API:`GET /advisories?affects={name}&ecosystem={eco}`。`affects` 参数接收 **只有包名称**(例如 `guzzlehttp/guzzle`) — 生态系统在其自己的参数中。前缀它(`composer:...`)返回 `200`,但列表静默为空。 - **冗余回退** — 当包的 GitHub 查找失败(例如,没有令牌的速率限制)时,会查询第二个来源,以便恢复结果而不是留下 `UNKNOWN`:Composer 的 **Packagist Security Advisories API** 和 npm/pnpm/bun/yarn 的 **npm audit** 批量端点。每个都是针对所有失败的包的一个批量请求。因此,可以不使用任何令牌就对每个生态系统进行审计。使用 `--no-packagist`/`--no-npm-audit` 禁用。 - **Semver** — 比较和范围满足使用 `composer/semver`,包括 GHSA 范围,其中逗号表示逻辑 AND(例如 `>= 7.0.0, < 7.4.5`)。 - **并发** — 每个包的注册表和咨询查找都会与 `Http::pool`(上限)并发执行,因此大型锁文件可以分几波审计,而不是一次请求一次。 - **缓存** — 注册表/咨询响应会以可配置的 TTL 存储到磁盘上,以便重复运行不会触碰到 API 速率限制。失败的查找永远不会缓存,因此下一次运行会重试暂时性错误。 ## 保持 CLI 更新 从发布的 PHAR 安装时: ``` secure-lock self-update # download and install the latest release secure-lock self-update --check # only check, don't install ``` 通过 Composer 安装时: ``` composer global update jeffersongoncalves/secure-lock-cli ``` ## 开发 ``` composer install composer test # Pint lint + PHPStan + Pest tests composer lint # Auto-fix style composer analyse # PHPStan (level 6) static analysis composer build # Build the PHAR into builds/secure-lock ``` 在测试套件中使用 `Http::fake()` 模拟 HTTP 调用。在测试期间创建的固定锁文件位于 `tests/tmp/`(git 忽略)。 ## 发布 1. 合并更改到 `main` — CI 构建 `builds/secure-lock` 对最新的标签,并将其提交回。 2. 创建一个新的 GitHub 发布(标签 `X.Y.Z`,没有 `v` 前缀)。 3. `publish-phar.yml` 工作流程将 `secure-lock.phar` 附带到发布,并 `update-changelog.yml` 更新 `CHANGELOG.md` + `version.txt`。 ## 路线图 核心功能集已完整(多生态系统审计、安全更新分类、`--fix`、冗余咨询回退、SARIF)。欢迎通过问题提出想法。
标签:Composer, ffuf, GitHub Advanced Security, GitHub API, Laravel Zero, npm, 供应链攻击, 包管理, 反取证, 安全修复, 安全加固, 安全可观测性, 安全响应, 安全扫描, 安全测试, 安全漏洞数据库, 安全评估, 攻击性安全, 时序注入, 暗色界面, 版本控制, 软件更新, 软件漏洞