pypa/abi3audit

GitHub: pypa/abi3audit

扫描 Python 扩展包的 abi3 稳定 ABI 合规性,检测版本声明与实际符号使用的不一致和违规。

Stars: 121 | Forks: 16

# abi3audit [![Tests](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/549cd96e4f194715.svg)](https://github.com/pypa/abi3audit/actions/workflows/tests.yml) [![PyPI version](https://badge.fury.io/py/abi3audit.svg)](https://pypi.org/project/abi3audit) [![Packaging status](https://repology.org/badge/tiny-repos/python:abi3audit.svg)](https://repology.org/project/python:abi3audit/versions) *[阅读 Trail of Bits 关于使用 `abi3audit` 发现漏洞的博客文章!](https://blog.trailofbits.com/2022/11/15/python-wheels-abi-abi3audit/)* `abi3audit` 扫描 Python 扩展以查找 `abi3` 违规和不一致情况。 它可以扫描单个(未打包的)共享对象、打包的 wheel 或整个 包版本历史。 ![abi3audit 运行时的动态演示](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/ffb869e905194718.gif) 该项目由 [Trail of Bits](https://trailofbits.com) 创建, 现作为 Python Packaging Authority (PyPA) 的一部分进行维护。 这不是 Trail of Bits 的官方产品。 ## 目录 * [动机](#motivation) * [安装](#installation) * [用法](#usage) * [示例](#examples) * [局限性](#limitations) * [许可](#licensing) ## 动机 CPython(Python 的参考实现)定义了一个稳定的 API 和相应的 ABI(“`abi3`”)。原则上,任何 CPython 扩展都可以针对此 API/ABI 构建,并保持与未来 CPython 次版本的向前兼容性。 换句话说:如果您针对 Python 3.5 的稳定 ABI 进行构建,您的 扩展无需修改即可在 Python 3.9 上运行。 稳定 ABI 简化了 CPython 扩展的打包,因为打包者 只需构建一个针对最低支持 Python 版本的 `abi3` wheel。 为了表明 Python wheel 包含 `abi3` 兼容的扩展, Python 打包生态系统使用 `abi3` wheel 标签,例如: ``` pyrage-1.0.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl ``` 不幸的是,在安装或运行时,对 Python 扩展的 `abi3` 合规性**没有实际强制措施**:一个被标记为 `abi3` 的 wheel(或独立的 共享对象)被假定是 `abi3` 的,但 不会以任何方式进行验证。 更糟糕的是,控制 wheel 标记的标志 ([`--py-limited-api`](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#setuptools.Extension)) 与实际上将 Python 扩展锁定到特定 `abi3` 版本的构建宏 ([`Py_LIMITED_API`](https://docs.python.org/3/c-api/stable.html#c.Py_LIMITED_API)) 之间**没有正式关联**。 结果就是:很容易将 Python 扩展编译为错误的 `abi3` 版本,或者将 Python wheel 标记为 `abi3` 而实际上并未将其编译为 `abi3` 兼容。 这具有严重的安全性和可靠性影响:CPython ABI 的非稳定部分 可能在次版本之间发生变化,当 Python 扩展错误地假设函数的参数 或结构的布局时,会导致崩溃、 不可预测的行为或潜在的利用内存损坏。 ## 安装 `abi3audit` 可通过 `pip` 获取: ``` pip install abi3audit ``` ## 用法 您可以将 `abi3audit` 作为独立程序运行,或通过 `python -m abi3audit` 运行: ``` abi3audit --help python -m abi3audit --help ``` ### 示例 审核单个共享对象、wheel 或 PyPI 包: ``` # 审核 abi3 扩展的本地副本 abi3audit procmaps.abi3.so # 审核 abi3 wheel 的本地副本 abi3audit procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl # 审核 PyPI 上 'procmaps' 包的每个 abi3 wheel abi3audit procmaps ``` 在审核时显示额外详细信息(漂亮的表格和个别违规): ``` abi3audit procmaps --verbose ``` 输出结果: ``` [17:59:46] 👎 procmaps: procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl: procmaps.abi3.so uses the Python 3.10 ABI, but is tagged for the Python 3.6 ABI ┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Symbol ┃ Version ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ PyUnicode_AsUTF8AndSize │ 3.10 │ └─────────────────────────┴─────────┘ [17:59:47] 💁 procmaps: 2 extensions scanned; 1 ABI version mismatches and 0 ABI violations found ``` 为每个输入生成 JSON 报告: ``` abi3audit procmaps --report | python -m json.tool ``` 输出结果: ``` { "specs": { "procmaps": { "kind": "package", "package": { "procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl": [ { "name": "procmaps.abi3.so", "result": { "is_abi3": true, "is_abi3_baseline_compatible": false, "baseline": "3.6", "computed": "3.10", "non_abi3_symbols": [], "future_abi3_objects": { "PyUnicode_AsUTF8AndSize": "3.10" } } } ], "procmaps-0.6.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl": [ { "name": "procmaps.abi3.so", "result": { "is_abi3": true, "is_abi3_baseline_compatible": true, "baseline": "3.7", "computed": "3.7", "non_abi3_symbols": [], "future_abi3_objects": {} } } ] } } } } ``` ## 局限性 `abi3audit` 是一个*尽力而为*的工具,具有与 [`auditwheel`](https://github.com/pypa/auditwheel) 相同的一些局限性。特别是: * `abi3audit` 无法检查*动态* abi3 违规,例如扩展 调用 [`dlsym(3)`](https://man7.org/linux/man-pages/man3/dlsym.3.html) 以在运行时调用非 abi3 函数。 * `abi3audit` 可以确认存在 abi3 兼容符号,但没 有详尽的 abi3 *不兼容*符号列表。相反,它通过查找不在 abi3 兼容列表中以 `Py_` 或 `_Py_` 开头的符号 来寻找违规。这*不太可能*导致误报, 但如果扩展错误地使用了那些保留前缀,则*可能* 发生。 * 在审核“裸”共享对象(例如 `foo.abi3.so`)时,`abi3audit` 无法 对最低*预期* abi3 版本做任何假设。相反,它 默认为最低已知 abi3 版本(`abi3-cp32`)并警告任何 版本不匹配(例如,仅在 3.6 中稳定的符号)。 这可能导致误报,因此鼓励用户审核整个 wheel 或包(因为它们包含足够的元数据)。 * `abi3audit` 考虑的是符号*稳定*时的 abi3 版本, 而不是*引入*时的版本。换句话说:即使 函数是在 3.6 中引入的,如果 `abi3-cp36` 扩展包含在 3.7 中稳定的函数,`abi3audit` 也会产生警告。这*不是*误报 (这是 ABI 版本不匹配),但*通常*不是漏洞的来源。 * `abi3audit` 检查每个扩展的“本地”和“外部”符号, 针对支持这两种符号的格式。这样做是为了捕获已内联的符号, 例如 `_Py_DECREF`。但是,如果扩展的符号表 已被剥离,这些可能会被遗漏。 ## 许可 `abi3audit` 根据 MIT 许可证授权。 `abi3audit` 包含根据 [Kaitai Struct](https://kaitai.io/) 项目提供的定义生成的 ASN.1 和 Mach-O 解析器。 这些内嵌的解析器由 Kaitai Struct 作者根据 MIT 许可证授权。
标签:abi3, CPython, DLL, ELF, PyPA, Python, Shared Object, wheel, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 兼容性检查, 威胁情报, 安全合规, 开发者工具, 扩展模块, 文档结构分析, 无后门, 网络代理, 软件供应链安全, 远程方法调用, 逆向工具, 逆向工程, 静态分析