pranavkumaarofficial/venvy
GitHub: pranavkumaarofficial/venvy
venvy 是一款离线、机器级 Python 供应链安全审计工具,可一次性扫描所有虚拟环境中的漏洞与恶意包,并提供语义化 JSON 输出供 CI 和 AI agent 使用。
Stars: 4 | Forks: 1
# venvy — 为每个虚拟环境提供离线 Python 供应链安全审计
**venvy** 扫描**您机器上的每一个 Python 虚拟环境**,查找**已知存在漏洞和恶意的软件包** —— 完全**离线**、确定性强,并且是您的 **CI pipeline 和 AI 编程 agent** 可以信任的形式。它还可以兼作轻量级的虚拟环境管理器(注册、检查点、安全安装)。
[](https://pypi.org/project/venvy/)
[](https://pypi.org/project/venvy/)
[](LICENSE)
[](#how-it-works)
[](#what-venvy-detects)
[](#json-output-for-ci--ai-agents)
## 目录
- [为什么使用 venvy](#why-venvy)
- [venvy 检测什么](#what-venvy-detects)
- [安装](#installation)
- [快速开始](#quick-start)
- [命令参考](#command-reference)
- [退出码](#exit-codes)
- [JSON 输出(用于 CI 和 AI agent)](#json-output-for-ci--ai-agents)
- [工作原理](#how-it-works)
- [venvy vs pip-audit vs safety](#venvy-vs-pip-audit-vs-safety)
- [虚拟环境管理](#virtual-environment-management)
- [常见问题解答](#faq)
- [覆盖范围与局限性](#coverage--limitations)
- [贡献](#contributing)
- [许可证](#license)
## 为什么使用 venvy
大多数 Python 安全扫描器一次只审计**一个项目**,需要**联网**,并且只查找 **CVE**。venvy 填补了它们无法同时满足的空白:
| 功能 | 含义 | 谁还支持 |
|---|---|---|
| **全机器范围** | 通过一条命令审计机器上的*每个*环境,而不是一次一个项目 | 默认情况下无人支持 |
| **离线优先** | 扫描在零网络环境下运行;仅需一次性的数据库下载作为唯一在线步骤 | pip-audit 不支持 |
| **CVE *和* 恶意软件** | 标记已知存在漏洞的版本**以及**已知恶意 / 域名仿冒(typosquat)的软件包 | 在单一工具中很少见 |
| **原生支持 Agent 与 CI** | 专为自动化设计的稳定 JSON schema + 语义化退出码 | 在其他工具中仅部分支持 |
**专为 AI 编程时代构建。** 无法信任 LLM 来回答“这个软件包安全吗?”—— 它会产生幻觉捏造 CVE。venvy 是一个**确定性的真实情况查询工具**,agent 可以调用它(`venvy audit --json`)并依赖其结果。
## venvy 检测什么
| 发现类型 | 描述 | 示例 |
|---|---|---|
| **存在漏洞** | 已安装的版本处于已知存在漏洞的范围内(CVE / GHSA / PYSEC) | `requests 2.19.0` → GHSA-…(已在 2.20 中修复) |
| **恶意** | 已安装的软件包/版本位于已知的恶意列表中 | `ctx`,`django`-typosquats |
| **域名仿冒** | 软件包名称与流行库的已知 typosquat 匹配 | `reqeusts` → “你是想输入 `requests` 吗?” |
| **未知** | 存在安全公告但无法界定版本范围 —— 予以呈现,绝不静默清除 | 报告为 `unknown` |
**设计上优先考虑正确性:**任何无法被明确评估的内容都会被报告为 `unknown`,绝对不会报告为“安全”。错误的“您是安全的”提示会被视为严重 Bug。
## 安装
```
pip install venvy
```
要求 **Python 3.8+**。可在 **Windows、macOS 和 Linux** 上运行。无需编译器,没有重量级依赖项。
## 快速开始
```
# 审计您机器上的所有已知环境。
# 首次运行时,venvy 会下载一次性的 advisory 数据库(约 30MB)。
# 此后的每次扫描均为完全离线。
venvy audit
# 审计单个环境
venvy audit --env .venv
# 适用于 CI 或 AI agent 的机器可读输出
venvy audit --json
# 更新 advisory 数据库,然后扫描
venvy audit --refresh
# 绝不访问网络;如果不存在本地数据库则失败(确定性 CI)
venvy audit --offline
```
示例输出:
```
vulnerabilities found - 1 app package(s) affected across 2 env(s) (+4 toolchain)
scanned 17 packages (16 unique) in 61ms
advisory database: 0.1 days old
/path/to/project/.venv
package version advisory severity fix
* pytest 8.4.2 GHSA-6w46-j5rx-g56g MODERATE 9.0.3
+ 19 toolchain finding(s) (pip/setuptools/wheel) - --include-toolchain to show
```
## 命令参考
### 安全审计
| 命令 | 描述 |
|---|---|
| `venvy audit` | 扫描所有已知环境(首次运行时自动获取数据库) |
| `venvy audit --env ` | 扫描特定环境(可重复使用) |
| `venvy audit --json` | 输出版本化的 JSON 报告(用于 CI / agent) |
| `venvy audit --refresh` | 下载最新的咨询数据库,然后进行扫描 |
| `venvy audit --offline` | 绝不访问网络;如果本地数据库不存在则失败 |
| `venvy audit --scan` | 同时发现磁盘上未注册的环境 |
| `venvy audit --include-toolchain` | 将 `pip`/`setuptools`/`wheel` 包含在发现结果和退出码中 |
**工具链处理:** `pip`、`setuptools` 和 `wheel` 几乎存在于每个 venv 中,并且包含许多安全公告。它们总是被*报告*,但默认情况下被排除在退出码限制之外,因此过时的捆绑 `pip` 绝不会掩盖真实的应用程序依赖项发现。使用 `--include-toolchain` 可以将它们也纳入限制。
### 环境管理
| 命令 | 描述 |
|---|---|
| `venvy ls` | 列出所有已注册的环境 |
| `venvy ensure` | 创建或验证环境(幂等操作) |
| `venvy safe-install ` | 安装软件包,失败时自动回滚 |
| `venvy checkpoint --name ` | 对环境状态进行快照 |
| `venvy rollback --latest` | 恢复到上一个检查点 |
| `venvy status` | 环境健康报告 |
| `venvy doctor` | 诊断设置问题 |
在任何命令后添加 `--json` 即可获得结构化输出。
## 退出码
venvy 返回**语义化退出码**,以便脚本、CI 门控和 agent 可以根据结果进行分支判断,而无需解析文本。
| 代码 | 含义 |
|---|---|
| `0` | 干净 —— 无任何发现 |
| `20` | 发现存在漏洞的软件包 |
| `21` | 发现恶意软件包 |
| `22` | 已完成但存在警告(数据库过时或未解决的未知情况) |
| `23` | 无咨询数据库(请运行 `venvy audit --refresh`) |
**优先级:** `恶意 (21)` > `存在漏洞 (20)` > `过时/部分 (22)` > `干净 (0)`。
```
# CI gate 示例:发现漏洞或恶意结果时使构建失败
venvy audit --offline --json
code=$?
if [ "$code" = "20" ] || [ "$code" = "21" ]; then exit 1; fi
```
## JSON 输出(用于 CI 和 AI agent)
`venvy audit --json` 输出**稳定的、带版本号**的 schema。关键字段:
| 字段 | 描述 |
|---|---|
| `schema_version` | 整数;仅在发生破坏性更改时递增 |
| `exit_code` / `success` | 退出码及其布尔映射 |
| `db.built_at` / `db.age_days` / `db.stale` | 咨询数据库的来源与新鲜度 |
| `db.sources[]` | 每个数据源及其 URL、SHA-256 和获取时间 |
| `summary` | 计数:扫描的环境数、软件包数、唯一软件包数、存在漏洞的、恶意的、未知的 |
| `environments[]` | 每个环境的 `findings[]`(软件包、版本、咨询 ID、严重程度、修复版本)和 `errors[]` |
未知情况和错误是**一等数组** —— 它们永远不会被省略,因此自动化程序可以区分“干净”和“无法确定”。
## 工作原理
1. 从 venvy 的本地注册表中**枚举**每个环境(加上可选的磁盘发现)。
2. 直接从 `*.dist-info` 元数据中**读取**每个环境已安装的软件包 —— **仅限文本,无子进程,且绝不导入被扫描的软件包**(导入恶意软件包会执行其代码)。
3. 使用精确的 PEP 440 版本范围评估,将每个 `name==version` 与**本地预构建的咨询数据库**进行**匹配**。没有网络,没有随机性,没有模型。
4. **报告**发现结果,提供真实的标题计数,恶意软件优先,并附带修复版本。
**咨询数据**是离线编译成的一个单一的 SQLite 索引,数据来自:
| 来源 | 贡献 |
|---|---|
| [OSV.dev](https://osv.dev) (PyPI) | 约 26,000 条安全公告,包括约 13,000 条已知恶意软件包记录 |
| [DataDog malicious-software-packages-dataset](https://github.com/DataDog/malicious-software-packages-dataset) | 精选的恶意 PyPI 软件包 |
| [ecosyste.ms typosquatting dataset](https://github.com/ecosyste-ms/typosquatting-dataset) | 名称到目标的 typosquat 映射 |
数据库作为一个快照提供;`venvy audit --refresh` 会重建它。venvy **绝不会用空或损坏的数据库覆盖可用的数据库**,并且拒绝使用不可用的数据库进行扫描(安全失败并返回退出码 `23`),而不是报告错误的“干净”状态。
## venvy vs pip-audit vs safety
| 功能 | venvy | pip-audit | safety |
|---|:---:|:---:|:---:|
| 扫描已安装软件包的 CVE | 是 | 是 | 是 |
| 检测恶意 / typosquat 软件包 | **是** | 否 | 部分 |
| 一次性审计**所有环境** | **是** | 否(基于项目) | 否 |
| 完全**离线**扫描 | **是** | 否 | 部分 |
| 机器可解析的 JSON | 是 | 是 | 是 |
| 语义化退出码 | 是 | 部分 | 部分 |
| 同时管理虚拟环境 | **是** | 否 | 否 |
| 许可证 | MIT | Apache-2.0 | MIT(数据库分层) |
*对比反映了每个工具默认的、免费提供的功能。pip-audit 和 safety 是出色的 CVE 扫描器;venvy 的优势在于结合了离线、全机器范围、感知恶意软件和原生支持 agent 的特性。*
## 虚拟环境管理
venvy 最初是作为一个对 agent 安全的环境管理器而诞生的,现在依然如此。它维护着您环境的本地 SQLite 注册表,并支持安全、幂等的工作流:
```
venvy ensure --python 3.11 --json # create/verify an environment
venvy safe-install requests flask --json # install with auto-rollback on failure
venvy checkpoint --name "before-refactor" # snapshot before risky changes
venvy rollback --latest # restore if something breaks
venvy ls --json # list all environments
```
## 常见问题解答
**`venvy audit` 真的是离线的吗?**
是的。扫描本身绝不会接触网络。唯一的在线步骤是一次性的咨询数据库下载(或者通过 `--refresh` 更新)。如果本地数据库不存在,请使用 `--offline` 让其直接硬失败。
**这与 `pip-audit` 有什么不同?**
`pip-audit` 是一个强大的、基于项目的在线 CVE 扫描器。venvy 增加了三个它在默认情况下不会做的事情:它一次扫描**每一个**环境,它可以**离线**工作,而且它还能检测**恶意/typosquat** 软件包 —— 而不仅仅是 CVE。
**它会运行它所扫描的软件包中的任何代码吗?**
不会。venvy 仅以文本形式读取 `*.dist-info` 元数据。它绝不会导入被扫描的软件包,也不会在目标环境内部运行 `pip`。
**我的 AI agent 可以使用它吗?**
可以 —— 这是一个主要的设计目标。`venvy audit --json` 返回具有语义化退出码的确定性、带版本的报告,因此 agent 获得的是真实情况,而不是幻觉答案。
**支持哪些 Python 版本和操作系统?**
支持在 Windows、macOS 和 Linux 上运行的 Python 3.8+。
**它可以审计 Conda 环境吗?**
它会审计任何环境(包括 Conda 环境)内部通过 `pip` 安装的软件包。Conda 渠道的软件包目前不在范围之内。
## 覆盖范围与局限性
- 检测的完整性仅与其公共数据源(OSV + DataDog + typosquat 列表)相当。venvy **不声称**知道每一个存在漏洞或恶意的软件包。
- 恶意软件包源会捕捉已确认、已发布的恶意行为者;全新的或已经被下架的软件包可能不会出现。
- 咨询数据在两次刷新之间会变旧。venvy 在每次运行时都会显示数据库年龄,并在数据库过时时降低退出码级别。
## 许可证
[MIT](LICENSE) © Pranav Kumaar
标签:Python, 无后门, 虚拟环境管理, 逆向工具