boredchilada/piptastic

GitHub: boredchilada/piptastic

Python 项目依赖审计工具,检测版本漂移和已知 CVE,并支持感知漏洞的安全版本重写。

Stars: 6 | Forks: 1

# piptastic 一个用于 Python 项目的依赖审计工具。它会遍历目录树,找到每一个声明了 依赖的项目,并针对每个版本锁定回答两个问题:*它过时了多久* 以及 *它是否存在漏洞*。它还可以选择将 `requirements.txt` 重写为 最新兼容版本,同时遵循来自 [pip-audit](https://github.com/pypa/pip-audit) 的 CVE 修复版本数据。 [![License: AGPL v3+](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue.svg)](LICENSE) [![Python: 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml) [![tests](https://static.pigsec.cn/wp-content/uploads/repos/cas/6b/6b52945adbf8d9e421fe243515ae54cfbd3da263f16b1eabda37cdc0b797b8eb.svg)](https://github.com/boredchilada/piptastic/actions/workflows/test.yml) [![JSON schema: v3](https://img.shields.io/badge/json--schema-v3-informational.svg)](#json-schema) 一次性 CLI。没有守护进程、没有服务器、没有共享状态。可用于运行 单个项目或包含数百个项目的目录树。 ## 目录 - [安装](#install) - [快速开始](#quickstart) - [设计说明](#design-notes) - [命令](#commands) - [工作流](#workflows) - [接受已知 CVE(抑制规则)](#accepting-known-cves-suppressions) - [参考](#reference) — 发现、解析、偏移、锁定姿态、 JSON schema、缓存、日志记录、退出代码 - [路线图](#roadmap) - [发布说明](#release-notes) - [许可证](#license) - [贡献](#contributing) - [致谢](#acknowledgements) ## 安装 ``` pip install git+https://github.com/boredchilada/piptastic # 或者,使用 PATH 上的 CLI 进行隔离安装: pipx install git+https://github.com/boredchilada/piptastic ``` 会安装两个入口点:`piptastic` 和 `ptc`(短别名)。如果不 安装,可以直接运行该包:`python -m piptastic`。 运行时要求:Python 3.10+,`packaging`,`rich`,`pip-audit`。在 Python < 3.11 上会自动引入 `tomli`。 `pip-audit` 会在底层作为 `python -m pip_audit` 被调用,因此在 Windows 上不需要 PATH 垫片。 ## 快速开始 审计单个项目: ``` piptastic audit . ``` 示例输出(表格视图,单项目的默认视图): ``` +-----------------------------------------------------------------------------------------+ | Project | Package | Current | Latest | Age | Min safe | Drift | Pin | Vulns |---------------+------------+----------+--------+------+----------+-------+-------+------ | my-flask-app | flask | 2.0.0 | 3.1.3 | 2mo | 3.1.0 | major | pinned| 2 | my-flask-app | requests | 2.31.0 | 2.34.2 | 1mo | 2.32.4 | minor | pinned| 1 | my-flask-app | sqlalchemy | 2.0.30 | 2.0.43 | 3mo | - | patch | pinned| - +-----------------------------------------------------------------------------------------+ ``` 审计整个目录树: ``` piptastic audit ~/code --summary ``` ``` +-----------------------------------------------------------------------------------------+ | Project | Py | Pin score | Major | Minor | Patch | Other | Yanked | Vulns | Deps |----------------+------+-----------+-------+-------+-------+-------+--------+-------+----- | my-flask-app | 3.11 | 100% | 1 | 1 | 1 | 0 | 0 | 3 | 3 | ingestion-svc | 3.12 | 60% | 0 | 2 | 5 | 0 | 1 | 0 | 12 | legacy-cron | 3.10 | 0% | 8 | 3 | 1 | 1 | 2 | 27 | 14 +-----------------------------------------------------------------------------------------+ 3 projects | 29 deps | 27 CVEs across 1 project(s) | 3 yanked ``` 对一个项目的 `requirements.txt` 应用感知 CVE 的版本提升: ``` piptastic update ~/code/legacy-cron # 7 个已升级,2 个由 CVE 驱动 ``` 预览而不写入: ``` piptastic update ~/code/legacy-cron --dry-run ``` ## 设计说明 代码库的结构反映了几个明确的选择: - **标准库 `urllib` 用于 PyPI,而不是 `requests`。** 少了一个运行时依赖。 PyPI 的 JSON endpoint 足够稳定,不需要重量级的客户端。 - **通过 subprocess 调用 `pip-audit`,而不是在 Python 中 import。** 该库的公共 接口就是 CLI。导入其内部实现会将 piptastic 耦合到一个 不断变化的目标上。 - **到处使用 Frozen dataclass。** `Dep`、`DepAudit`、`ProjectAudit`、 `Vulnerability` 全部是不可变的。通过重建进行修改;新字段会带有 默认值,因此旧的调用处仍能正常工作。领域逻辑存在于 `analysis.py` 中,而不是 dataclass 上。 - **按源文件缓存。** PyPI 元数据按发行版名称缓存; pip-audit 结果按 `(name, version)` 对缓存。空漏洞结果也 会被缓存——干净的版本锁定不会在后续运行中重新调用 subprocess。 - **优雅降级,绝不静默。** PyPI 缺失会变成 `drift=unknown` 并显示在 `pypi_unreachable` 中。pip-audit 缺失会显示在 `vuln_unreachable` 中(不会被静默报告为干净)。单个项目的失败 不会终止整个目录树的扫描。 - **严格的退出代码约定。** `0` 干净,`1` 操作错误,`2` 重写已回滚,`3` 触发策略门禁。CI 可以区分“你 配置错了”和“门禁生效了”。 - **带版本控制的单一输出 schema。** JSON 输出会声明 `schema_version`。新增更改不会提升版本;字段重命名/删除 则会提升版本。文档记录在 [schema 版本历史](#schema-version-history)中。 ## 命令 ### `audit ` 只读。发现 `` 下的 Python 项目,并报告每个 依赖的锁定姿态、相对于 PyPI 的偏移以及已知 CVE。 | Flag | 效果 | | --- | --- | | `--table` | 平铺表格视图(单项目的默认视图)。 | | `--summary` | 每个项目一行:偏移直方图(Major / Minor / Patch,加上折叠了构建和 epoch 偏移的 `Other` 列)+ 锁定分数 + CVE 汇总。 | | `--json` | 输出到 stdout 的机器可读 JSON。参见 [JSON schema](#json-schema)。 | | `--sarif` | 用于 GitHub Code Scanning 的 SARIF 2.1.0 输出。与 `--json` 互斥。 | | `--include-prereleases` | 将预发布版本视为“最新”的候选。 | | `--exclude PATTERN` | 与目录基名匹配的 Glob。可重复使用。叠加在内置跳过列表之上。 | | `--no-cache` | 本次运行跳过磁盘上的 PyPI 缓存。 | | `--refresh-cache` | 强制重新获取并重写缓存。 | | `--cache-ttl SECONDS` | 覆盖默认 TTL(3600)。 | | `--concurrency N` | PyPI 获取线程池大小。 | | `--no-vulns` | 完全跳过 pip-audit CVE 扫描。与 `--fail-on-vuln` 互斥。 | | `--vulnerable-only` | 仅显示带有非抑制 CVE 的依赖。匹配数为零的项目将被丢弃。 | | `--drift-min {build,patch,minor,major,epoch}` | 仅显示偏移 ≥ 此级别的依赖。 | | `--direct-only` | 从输出中隐藏传递性 lockfile 依赖。仅用于显示——门禁仍会评估完整的解析图。 | | `--fail-on-drift {build,patch,minor,major,epoch}` | 当任何依赖的偏移 ≥ 此级别时退出代码为 `3`。 | | `--fail-on-age DAYS` | 当任何依赖的最新发布时间超过 `DAYS` 时退出代码为 `3`。发布日期未知的依赖(PyPI 缺失)永远不会触发它。 | | `--fail-on-vuln any\|N` | 当任何依赖具有非抑制 CVE(`any`)或整个目录树的 CVE 计数 ≥ N 时退出代码为 `3`。 | | `--strict-vuln-gate` | 设置了 `--fail-on-vuln` 时,也会对 `vuln_unreachable` 的包触发。默认值为 fail-open 并给出警告。 | 默认视图:对于多项目路径显示树形结构(项目 → 文件 → 依赖),对于 单个项目显示表格。当展示多个项目时,终端输出会以 单行统计结束——包含项目和依赖数量,以及不为零时的 CVE 和 yanked 总数。 ### `update [packages ...]` 就地修改 `requirements.txt`。将每个锁定的依赖解析为最新 兼容的发行版(`~=` 仍保持兼容发行版,`>=` 底线仍保持为 底线),写入备份,在临时的 venv 中运行测试安装,如果 安装失败则回滚。 默认情况下,针对每个 `==` 锁定查询 pip-audit,如果当前锁定被未决的咨询覆盖, 则将提升目标提升至最低安全版本。 受 CVE 驱动的提升会在输出中注明: ``` flask: 2.0.0 -> 2.2.5 (CVE floor: PYSEC-2023-62) ``` | Flag | 效果 | | --- | --- | | `--dry-run` | 计算可能发生的更改;不写入文件、创建备份或运行测试安装。仍会进行 CVE 底线查找,因此预览结果是准确的。 | | `--no-test` | 跳过测试安装步骤。 | | `--refresh` | 绕过 PyPI 和漏洞缓存(等同于 `audit` 中的 `--refresh-cache`)。 | | `--temp-test-env` | 将临时测试安装 venv 放在 OS 临时目录下,而不是项目旁边的 `.piptastic_test_/` 中。 | | `--no-apply-cce-floor` | 禁用感知 CVE 的底线;照常选择最新未被 yanked 的发行版。 | 位置参数 `packages` 会将更新限制在这些发行版中。仅 会修改 `requirements*.txt` 家族文件;`pyproject.toml` 和 `Pipfile` 重写尚未实现。 ### `stats ` 基于同一审计流水线的跨项目汇总。终端输出会显示 被依赖最多的包、跨目录树的版本碎片化、yanked 锁定、未锁定的项目,以及全目录树的偏移 / 锁定姿态直方图。 | Flag | 效果 | | --- | --- | | `--top N` | Top-N 包列表大小(默认为 20)。 | | `--json` | 输出到 stdout 的机器可读 JSON。 | | `--exclude`, `--no-cache`, `--refresh-cache`, `--cache-ttl`, `--concurrency` | 与 `audit` 相同。 | ### `bootstrap ` 根据项目 venv 中安装的包生成 `requirements.txt`。 输出为排序后的 `name==X.Y.Z` 行,venv 自带的基础包(`pip`、`setuptools`、 `wheel`、`pkg_resources`、`distlib`、`_distutils_hack`)以及任何可编辑的 项目自安装都会被过滤掉。 | Flag | 效果 | | --- | --- | | `--venv PATH` | 显式指定 venv 目录。当存在多个 venv 并且你想要明确指定时是必填项。 | | `--force` | 覆盖现有的 `requirements.txt`。之前的文件会先被复制到 `.requirements_backups/requirements__.txt`。 | | `--dry-run` | 打印到 stdout;不进行任何写入。 | 自动发现会探测 `.venv`、`venv`、`env`、`.env` 中的 `pyvenv.cfg`,然后 回退到扫描项目的顶层子目录。如果找到零个或 多个候选者,且未提供 `--venv`,该命令将在不写入的情况下退出。 ## 工作流 ### 查找过时的内容 ``` piptastic audit . # full table for one project piptastic audit ~/code --summary # one row per project across a tree ``` 偏移列告诉你 `X.Y.Z` 的哪一部分发生了变动。`Age` 列 会显示那些即使偏移为 `none`,但也已经好几年没有发布过的包。 ### 将锁定提升到最新兼容版本 ``` piptastic update . piptastic update . flask requests # limit to specific packages piptastic update . --no-test # skip the test install piptastic update . --dry-run # preview without writing piptastic update . --refresh # bypass caches for a fresh fetch ``` 对于每个 `==` 锁定,会选择现有说明符允许的、最新未被 yanked 的稳定发行版, 如果 pip-audit 报告 所选版本仍处于易受攻击的范围内,则会进一步提升。 ### 查找已知存在 CVE 的项目 ``` piptastic audit ~/code --summary --vulnerable-only ``` 汇总中的 Vulns 列会汇总每个项目的咨询信息。深入了解某个项目: ``` piptastic audit ~/code/legacy-cron --table --vulnerable-only ``` Min safe(最低安全)列给出了解决影响当前锁定的所有咨询 的最低版本。应用方法: ``` piptastic update ~/code/legacy-cron ``` CVE 底线默认开启;传递 `--no-apply-cve-floor` 可将其禁用。 为了便于流水线消费,JSON 输出包含了每个依赖的完整 `vulnerabilities[]` 数组: ``` piptastic audit ~/code --json | jq ' .projects[] | {name, vuln_count, vulnerable_deps: [.deps[] | select(.vulnerabilities | length > 0) | {name, current, min_safe_version, vulns: [.vulnerabilities[].id]}]}' ``` ### 在 CI 中阻止过时或带有漏洞的 PR ``` piptastic audit . --fail-on-drift minor --fail-on-vuln any ``` 如果任何依赖的偏移量达到或超过 `minor`,或者任何依赖有 非抑制的 CVE,则退出代码为 `3`。退出代码 `1` 保留用于操作错误;退出代码 `0` 表示干净。 GitHub Actions: ``` - name: Audit dependencies run: | pip install git+https://github.com/boredchilada/piptastic piptastic audit . --fail-on-drift minor --fail-on-vuln any ``` 或者上传 SARIF,以便在 Security 选项卡中渲染发现结果: ``` - name: Audit dependencies (SARIF) run: | pip install git+https://github.com/boredchilada/piptastic piptastic audit . --sarif > piptastic.sarif - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: piptastic.sarif ``` ### 从 venv 恢复丢失的 requirements.txt ``` piptastic bootstrap . --dry-run # preview piptastic bootstrap . # write requirements.txt piptastic bootstrap . --force # overwrite (existing file is backed up) piptastic bootstrap . --venv .venv # disambiguate when multiple venvs exist ``` ### 调查整个代码文件夹的依赖健康度 ``` piptastic stats ~/code piptastic stats ~/code --json > stats.json ``` 显示被依赖最多的包、版本碎片化的包(在不同 项目中锁定不同版本的同名包)、仍在发布的 yanked 锁定, 以及整个目录树的直方图。 ### 在依赖之前评估第三方项目 ``` piptastic audit /path/to/their/repo --summary ``` 锁定分数、偏移计数器、漏洞计数以及最新发行版存在时间列 可以让你快速了解项目的维护姿态。 ## 接受已知 CVE(抑制规则) 当某个咨询仅在名义上影响你——未执行易受攻击的代码路径、 在更高层已经实施了缓解措施、修复程序尚不可用——可以在项目的 `pyproject.toml` 中添加抑制规则: ``` [tool.piptastic] [[tool.piptastic.suppressions]] package = "flask" cve = "PYSEC-2023-62" # also matches the advisory's aliases reason = "we do not use sessions" expires = "2026-12-31" # required; past-expiry rules are ignored ``` 这四个字段都是必填的。过期的规则会被忽略并记录在日志中,这样 它们就不会存在。在接下来的 30 天内即将过期的规则会 在其仍处于活动状态时发出提醒警告,从而确保被接受的 CVE 不会在到期之日 静默重新激活(并触发 `--fail-on-vuln`)。每条规则都会匹配规范咨询 id 或 pip-audit 报告的任何别名(GHSA / CVE / PYSEC)。`package = "*"` 会抑制项目中所有包的 CVE。 没有 `pyproject.toml` 的项目可以在根目录使用同级的 `.piptastic.toml` 配置规则: ``` [[suppressions]] package = "requests" cve = "CVE-2024-1234" reason = "patched at the proxy" expires = "2099-01-01" ``` 效果: - `vuln_count` 和 `--fail-on-vuln` 仅计算非抑制的咨询。 - `min_safe_version` 仅根据非抑制的咨询计算;`update` 不会针对已接受的 CVE 提升锁定。 - 完整的咨询仍会输出在 JSON(`suppressed: true` 加上 `suppression` 块)和 SARIF(`suppressions: [{kind: "external"}]`)中,因此 外部审计员可以看到它。 ## 参考 ### 漏洞查找 每次 `audit` 运行都会在获取 PyPI 元数据的同时查询 pip-audit。pip-audit 会针对 piptastic 已经解析好的 `(name, version)` 对作为 `python -m pip_audit -r --format json --no-deps --disable-pip` 被调用,因此没有单独的 依赖解析步骤。 每个依赖的结果: - `vulnerabilities` — 咨询列表:GHSA / PYSEC / CVE id、别名、 修复版本、上游描述。 - `min_safe_version` — 比已安装锁定更新的、每个咨询最低修复版本中的 最大值。升级到此版本可解决所有已知 咨询。当没有适用的咨询,或者没有比当前锁定更新的已知修复时,为 `null`。 每个项目的汇总: - `vuln_count` — 所有依赖中非抑制咨询的计数, 按咨询 id 去重(pip-audit 可能会针对每个受影响版本范围报告一次相同的咨询; 这些会被合并,因此计数不会膨胀)。 - `vuln_unreachable` — pip-audit 未能返回状态的包。 显示为“unknown”,绝不会被静默视为干净。 - `suppressed_count` — 接受风险的咨询,来自 `[tool.piptastic.suppressions]`。 ### 项目发现 如果一个目录包含以下任何内容,则它是一个 Python 项目: - `requirements*.txt`(包括 `requirements-dev.txt` 等) - 带有 `[project]` 或 `[tool.poetry]` 表的 `pyproject.toml` - `Pipfile` - `uv.lock`、`poetry.lock` 或 `pdm.lock` 遍历会跳过 `.git`、`.venv`、`venv`、`env`、`.env`、`node_modules`、 `__pycache__`、`site-packages`、`build`、`dist`、`.tox`、`.nox`、 `.mypy_cache`、`.pytest_cache`、`.ruff_cache`,以及任何包含 `pyvenv.cfg` 的目录。`--exclude PATTERN` 会添加到此列表中,并接受 与目录基名匹配的 glob 语法。 需求文件内部的 `-r other.txt` / `-c constraints.txt` 包含内容会 在带有循环检测的情况下被跟踪。每个依赖都归因于最初 声明它的文件,而不是包含它的文件。 ### 依赖解析 | 来源 | 读取内容 | | --- | --- | | `requirements*.txt` 家族 | PEP 508 说明符;带循环检测的 `-r` / `-c` 包含;遵循环境标记;URL / VCS / 本地路径要求显示为 `URL` 姿态。没有 `#egg=name` 的纯 `git+https://…` 行会根据 repo 路径命名,因此它仍然会被显示。 | | `pyproject.toml` (PEP 621) | `[project].dependencies` 以及 `[project.optional-dependencies]` 下的每个列表。 | | `pyproject.toml` (Poetry) | `[tool.poetry.dependencies]` 和 `[tool.poetry.group..dependencies]`。插入符号(`^1.2.3`)和波浪号(`~1.2.3`)简写会被展开为 PEP 440 范围。`python` 会被排除。多重约束依赖(一个用于特定平台锁定的 `{version, markers}` 表列表)会变成每个条目一个依赖,各自带有自己的说明符和标记。 | | `Pipfile` | `[packages]` 和 `[dev-packages]`。 | | `Pipfile.lock` | 来自 `default` 和 `develop` 部分的带哈希锁定行。 | | `uv.lock` / `poetry.lock` / `pdm.lock` | 完整的解析图——每个 `[[package]]` 条目作为一个精确锁定(直接**和**传递)。存在 lockfile 时,它会取代其清单(匹配的 `pyproject.toml` 源会被跳过以避免重复计算);仍会读取清单以标记哪些条目是直接依赖。传递条目会在输出中标记,并在 JSON 中标记为 `direct: false`。项目自己的可编辑/虚拟条目会被跳过。 | `requirements*.txt` 文件会被解码为 UTF-8(允许 UTF-8 BOM)。如果检测到 UTF-16 或 UTF-32 字节顺序标记,则会相应地解码,因此由 PowerShell 的 `pip freeze > requirements.txt`(在 Windows 上为 UTF-16-LE)编写的文件 会被正确解析,而不是被静默丢弃。 ### 偏移分类 对于每个具有可比较的声明/最新版本的依赖,偏移会根据 声明版本与最新匹配的 PyPI 发行版之间变动的片段 进行分类: | 层级 | 含义 | | --- | --- | | `NONE` | 声明版本等于最新版本。 | | `BUILD` | 仅第 4 段及以后的片段发生变动。 | | `PATCH` | 第 3 段(`X.Y.Z` 中的 `Z`)。 | | `MINOR` | 第 2 段。 | | `MAJOR` | 第 1 段。 | | `EPOCH` | PEP 440 epoch(`N!X.Y.Z`)发生变动。罕见。 | ### 锁定姿态 说明符的*形状*(而不是版本值)决定了姿态: | 姿态 | 示例 | | --- | --- | | `PINNED` | `flask==2.3.0`, `flask===2.3.0` | | `COMPATIBLE` | `flask~=2.3.0`(PEP 440 兼容发行版) | | `RANGE` | `flask>=2.0,<3.0` | | `FLOOR` | `flask>=2.0`(开放上限) | | `UNPINNED` | `flask`(无说明符) | | `URL` | `flask @ git+https://...`,本地路径,直接 URL | **Pin score** 是项目中处于 `PINNED` 或 `COMPATIBLE` 状态的非 URL 依赖的百分比。所有依赖都是 `URL` 的项目显示为 `n/a`——URL 锁定取决于 URL 是否锁定了一个引用,而审计器无法 可靠地判断这一点。 ### JSON schema `audit --json` 和 `stats --json` 都会生成 `schema_version: 3`。破坏性更改会提升版本; 附加更改则不会。顶层的鉴别器是 `kind`:`audit --json` 对应 `"audit"`,`stats --json` 对应 `"stats"`。 每个依赖的字段(audit): ``` { "name": "flask", "current": "2.0.0", "latest": "3.0.4", "drift": "major", "pin_status": "pinned", "yanked": false, "vulnerabilities": [ { "id": "PYSEC-2023-62", "aliases": ["CVE-2023-30861", "GHSA-m2qf-hxjv-5gpq"], "fix_versions": ["2.2.5", "2.3.2"], "description": "Flask session cookie issue ...", "suppressed": false, "suppression": null } ], "min_safe_version": "2.2.5", "latest_release_date": "2024-09-10T00:00:00+00:00", "latest_release_age_days": 261, "warnings": ["1 vulnerability(ies): PYSEC-2023-62"] } ``` 每个项目的字段(audit):`pinning_score`、`drift_summary`、`yanked_count`、 `pypi_unreachable`、`vuln_count`、`vuln_unreachable`、`suppressed_count`。 #### Schema 版本历史 | 版本 | 发布 | 更改 | | --- | --- | --- | | `1` | v0.2.0 | 初始公开 schema。 | | `2` | v0.3.0 | 每个依赖增加了 `vulnerabilities[]` 和 `min_safe_version`;每个项目增加了 `vuln_count` 和 `vuln_unreachable`。 | | `3` | v0.4.0 | 每个依赖增加了 `latest_release_date` 和 `latest_release_age_days`;每个漏洞增加了 `suppressed` 和可选的 `suppression` 块;每个项目增加了 `suppressed_count`。全部为附加更改。 | 自 v3 以来的附加更改(无版本提升):每个依赖的 `direct` 布尔值(对于 传递性 lockfile 条目为 false),添加于 v0.6.0。 ### 缓存 PyPI 元数据和 pip-audit 结果会分别缓存在磁盘上独立的 目录中。 | 来源 | POSIX 默认值 | Windows 默认值 | | --- | --- | --- | | PyPI 元数据 | `$XDG_CACHE_HOME/piptastic/pypi/` → `~/.cache/piptastic/pypi/` | `%USERPROFILE%\.cache\piptastic\pypi\` | | pip-audit 结果 | `$XDG_CACHE_HOME/piptastic/vulns/` → `~/.cache/piptastic/vulns/` | `%USERPROFILE%\.cache\piptastic\vulns\` | 使用 `PIPTASTIC_CACHE_DIR=` 覆盖父目录。两者的默认 TTL 均为 3600s(1 小时)。PyPI 条目是按发行版的 JSON;漏洞条目是按 `(name, version)` 的 JSON,包括干净锁定的空结果。随时 可以安全地删除这两个目录。 ### 日志 `-v` / `--verbose` 将根 logger 设置为 INFO。`-q` / `--quiet` 会静默 ERROR 以下的所有内容。`--log-file PATH` 会将日志记录镜像到文件中,而 stderr 流保持不变。默认值为输出到 stderr 的 WARNING。 ### 退出代码 | 代码 | 含义 | | --- | --- | | `0` | 审计完成;未触发门禁。过时或易受攻击的依赖本身不会改变退出代码。 | | `1` | 操作失败:路径不存在、未找到 Python 项目、输入格式错误、内部崩溃。PyPI / pip-audit 不可达不会提升此代码——两者都会优雅降级。 | | `2` | `update` 测试安装失败;requirements 文件已从备份回滚。 | | `3` | 触发策略门禁:`--fail-on-drift`、`--fail-on-vuln` 和/或 `--fail-on-age`。审计本身已成功执行。 | 以前检查 `==1` 来判断是否触发门禁的 CI 消费者应切换到 `==3`(v0.4 约定更改)。 ## 路线图 推迟到未来版本发布。顺序大致按优先级排列,并非发布计划: - Lockfile 偏移检测(`Pipfile` ↔ `Pipfile.lock`、`poetry.lock`、 `uv.lock`)。 - 针对 `pyproject.toml` 和 `Pipfile` 执行 `update`。 - `setup.py` / `setup.cfg` 解析。 - HTML 报告输出。 - 监视 / 守护进程模式。 - 发布到 PyPI(目前需从源码 / git 安装)。 ## 发布说明 [CHANGELOG.md](CHANGELOG.md) 记录了每次发布。Schema 提升和破坏性 flag 更改会列在“Breaking”标题下。 ## 许可证 AGPL-3.0-or-later。完整文本请见 [LICENSE](LICENSE)。 AGPL 的网络服务条款适用:如果你将修改后的 piptastic 版本作为网络服务提供,你必须向该版本 的用户提供其源代码。对于不适合使用 AGPL 的商业部署, 请联系维护者洽谈商业许可。 ## 贡献 欢迎提交 Issue 和 PR。提交贡献即表示你同意将其 在项目的许可下(AGPL-3.0-or-later)分发。 工程约定(frozen dataclass、I/O 边界、JSON-schema 版本控制规则、跨平台限制)记录在 [CLAUDE.md](CLAUDE.md) 中。在开启重要的 PR 之前请阅读它;无论 贡献者是人类还是 AI 代理,都适用相同的约定。 ## 致谢 piptastic 构建于几个维护良好的库之上: - [packaging](https://github.com/pypa/packaging) (PyPA) — PEP 440 版本、 说明符和标记解析。偏移和锁定姿态模型基于 其 `Version` 和 `SpecifierSet` 构建。 - [rich](https://github.com/Textualize/rich) — 终端表格、树状结构 和进度条。 - [pip-audithttps://github.com/pypa/pip-audit) (PyPA) — CVE 扫描。 piptastic 将其作为 subprocess 调用,而不是重新实现咨询 匹配。 - [tomli](https://github.com/hukkin/tomli) — Python 3.10 上的 TOML 解析 (3.11+ 使用标准库 `tomllib`)。 - [hatchling](https://github.com/pypa/hatch) — 构建后端。 - [pytest](https://github.com/pytest-dev/pytest) — 测试套件。 审计中显示的漏洞咨询来自 pip-audit 的数据 源——主要是 [PyPI Advisory Database](https://github.com/pypa/advisory-database) 和 [OSV](https://osv.dev/)——而包的元数据来自 [PyPI JSON API](https://warehouse.pypa.io/api-reference/json.html)。感谢上述所有项目 的维护者。
标签:CISA项目, Python, SOC Prime, 依赖管理, 域名收集, 开发工具, 无后门, 逆向工具