用于扫描Python环境中已知漏洞的工具
项目描述
pip-audit
pip-audit
是一个用于扫描Python环境中存在已知漏洞的包的工具。它通过 PyPI JSON API 使用 Python打包咨询数据库 作为漏洞报告的来源。
本项目部分由 Trail of Bits 维护,并获得 Google 的支持。这不是 Google 或 Trail of Bits 的官方产品。
目录
功能
- 支持审计本地环境和要求风格文件
- 支持多个漏洞服务(PyPI,OSV)
- 支持以 CycloneDX XML 或 JSON 格式输出 SBOMs
- 支持自动修复漏洞依赖项(
--fix
) - 人类和机器可读的输出格式(列式、Markdown、JSON)
- 无缝重用现有的本地
pip
缓存
安装
pip-audit
需要 Python 3.8 或更高版本,并且可以直接通过 pip
安装
python -m pip install pip-audit
第三方包
存在多个 第三方 的 pip-audit
包。下面的矩阵和徽章列出了一些
特别是,pip-audit
可以通过 conda
安装
conda install -c conda-forge pip-audit
第三方包不直接由本项目支持。有关更详细的安装指南,请参阅您的包管理器文档。
GitHub Actions
pip-audit
有一个官方的 GitHub Action!
您可以从 GitHub Marketplace 安装它,或者手动将其添加到您的 CI 中
jobs:
pip-audit:
steps:
- uses: pypa/[email protected]
with:
inputs: requirements.txt
有关更多详细信息和使用示例,请参阅 操作文档。
pre-commit
支持
pip-audit
支持 pre-commit
。
例如,使用 pre-commit
通过 pip-audit
审计一个需求文件
- repo: https://github.com/pypa/pip-audit
rev: v2.7.3
hooks:
- id: pip-audit
args: ["-r", "requirements.txt"]
ci:
# Leave pip-audit to only run locally and not in CI
# pre-commit.ci does not allow network calls
skip: [pip-audit]
以下文档中的任何 pip-audit
参数都可以传递。
用法
您可以将 pip-audit
作为独立程序运行,或通过 python -m
pip-audit --help
python -m pip_audit --help
usage: pip-audit [-h] [-V] [-l] [-r REQUIREMENT] [-f FORMAT] [-s SERVICE] [-d]
[-S] [--desc [{on,off,auto}]] [--aliases [{on,off,auto}]]
[--cache-dir CACHE_DIR] [--progress-spinner {on,off}]
[--timeout TIMEOUT] [--path PATH] [-v] [--fix]
[--require-hashes] [--index-url INDEX_URL]
[--extra-index-url URL] [--skip-editable] [--no-deps]
[-o FILE] [--ignore-vuln ID] [--disable-pip]
[project_path]
audit the Python environment for dependencies with known vulnerabilities
positional arguments:
project_path audit a local Python project at the given path
(default: None)
optional arguments:
-h, --help show this help message and exit
-V, --version show program's version number and exit
-l, --local show only results for dependencies in the local
environment (default: False)
-r REQUIREMENT, --requirement REQUIREMENT
audit the given requirements file; this option can be
used multiple times (default: None)
-f FORMAT, --format FORMAT
the format to emit audit results in (choices: columns,
json, cyclonedx-json, cyclonedx-xml, markdown)
(default: columns)
-s SERVICE, --vulnerability-service SERVICE
the vulnerability service to audit dependencies
against (choices: osv, pypi) (default: pypi)
-d, --dry-run without `--fix`: collect all dependencies but do not
perform the auditing step; with `--fix`: perform the
auditing step but do not perform any fixes (default:
False)
-S, --strict fail the entire audit if dependency collection fails
on any dependency (default: False)
--desc [{on,off,auto}]
include a description for each vulnerability; `auto`
defaults to `on` for the `json` format. This flag has
no effect on the `cyclonedx-json` or `cyclonedx-xml`
formats. (default: auto)
--aliases [{on,off,auto}]
includes alias IDs for each vulnerability; `auto`
defaults to `on` for the `json` format. This flag has
no effect on the `cyclonedx-json` or `cyclonedx-xml`
formats. (default: auto)
--cache-dir CACHE_DIR
the directory to use as an HTTP cache for PyPI; uses
the `pip` HTTP cache by default (default: None)
--progress-spinner {on,off}
display a progress spinner (default: on)
--timeout TIMEOUT set the socket timeout (default: 15)
--path PATH restrict to the specified installation path for
auditing packages; this option can be used multiple
times (default: [])
-v, --verbose run with additional debug logging; supply multiple
times to increase verbosity (default: 0)
--fix automatically upgrade dependencies with known
vulnerabilities (default: False)
--require-hashes require a hash to check each requirement against, for
repeatable audits; this option is implied when any
package in a requirements file has a `--hash` option.
(default: False)
--index-url INDEX_URL
base URL of the Python Package Index; this should
point to a repository compliant with PEP 503 (the
simple repository API); this will be resolved by pip
if not specified (default: None)
--extra-index-url URL
extra URLs of package indexes to use in addition to
`--index-url`; should follow the same rules as
`--index-url` (default: [])
--skip-editable don't audit packages that are marked as editable
(default: False)
--no-deps don't perform any dependency resolution; requires all
requirements are pinned to an exact version (default:
False)
-o FILE, --output FILE
output results to the given file (default: stdout)
--ignore-vuln ID ignore a specific vulnerability by its vulnerability
ID; this option can be used multiple times (default:
[])
--disable-pip don't use `pip` for dependency resolution; this can
only be used with hashed requirements files or if the
`--no-deps` flag has been provided (default: False)
退出代码
完成时,pip-audit
将退出并返回表示其状态的代码。
当前的代码是
0
:未检测到已知漏洞。1
:发现一个或多个已知漏洞。
pip-audit
的退出代码不能被抑制。有关支持的替代方案,请参阅 抑制 pip-audit
的退出代码。
模拟运行
pip-audit
支持使用 --dry-run
标志来控制是否实际执行审计(或修复)步骤。
- 单独使用
pip-audit --dry-run
时,将跳过审计步骤并打印出将要审计的依赖项数量。 - 在修复模式下,使用
pip-audit --fix --dry-run
执行审计步骤并打印出将要执行的修复行为(即哪些依赖项将被升级或跳过)。
示例
审计当前 Python 环境的依赖项
$ pip-audit
No known vulnerabilities found
审计给定需求文件的依赖项
$ pip-audit -r ./requirements.txt
No known vulnerabilities found
审计需求文件的依赖项,排除系统包
$ pip-audit -r ./requirements.txt -l
No known vulnerabilities found
审计本地 Python 项目的依赖项
$ pip-audit .
No known vulnerabilities found
pip-audit
在提供的路径中搜索各种 Python "项目" 文件。目前仅支持 pyproject.toml
。
存在漏洞时审计依赖项
$ pip-audit
Found 2 known vulnerabilities in 1 package
Name Version ID Fix Versions
---- ------- -------------- ------------
Flask 0.5 PYSEC-2019-179 1.0
Flask 0.5 PYSEC-2018-66 0.12.3
审计包括别名的依赖项
$ pip-audit --aliases
Found 2 known vulnerabilities in 1 package
Name Version ID Fix Versions Aliases
---- ------- -------------- ------------ -------------------------------------
Flask 0.5 PYSEC-2019-179 1.0 CVE-2019-1010083, GHSA-5wv5-4vpf-pj6m
Flask 0.5 PYSEC-2018-66 0.12.3 CVE-2018-1000656, GHSA-562c-5r94-xh97
审计包括描述的依赖项
$ pip-audit --desc
Found 2 known vulnerabilities in 1 package
Name Version ID Fix Versions Description
---- ------- -------------- ------------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Flask 0.5 PYSEC-2019-179 1.0 The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656.
Flask 0.5 PYSEC-2018-66 0.12.3 The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083.
以 JSON 格式审计依赖项
$ pip-audit -f json | python -m json.tool
Found 2 known vulnerabilities in 1 package
[
{
"name": "flask",
"version": "0.5",
"vulns": [
{
"id": "PYSEC-2019-179",
"fix_versions": [
"1.0"
],
"aliases": [
"CVE-2019-1010083",
"GHSA-5wv5-4vpf-pj6m"
],
"description": "The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656."
},
{
"id": "PYSEC-2018-66",
"fix_versions": [
"0.12.3"
],
"aliases": [
"CVE-2018-1000656",
"GHSA-562c-5r94-xh97"
],
"description": "The Pallets Project flask version Before 0.12.3 contains a CWE-20: Improper Input Validation vulnerability in flask that can result in Large amount of memory usage possibly leading to denial of service. This attack appear to be exploitable via Attacker provides JSON data in incorrect encoding. This vulnerability appears to have been fixed in 0.12.3. NOTE: this may overlap CVE-2019-1010083."
}
]
},
{
"name": "jinja2",
"version": "3.0.2",
"vulns": []
},
{
"name": "pip",
"version": "21.3.1",
"vulns": []
},
{
"name": "setuptools",
"version": "57.4.0",
"vulns": []
},
{
"name": "werkzeug",
"version": "2.0.2",
"vulns": []
},
{
"name": "markupsafe",
"version": "2.0.1",
"vulns": []
}
]
审计并尝试自动升级漏洞依赖项
$ pip-audit --fix
Found 2 known vulnerabilities in 1 package and fixed 2 vulnerabilities in 1 package
Name Version ID Fix Versions Applied Fix
----- ------- -------------- ------------ ----------------------------------------
flask 0.5 PYSEC-2019-179 1.0 Successfully upgraded flask (0.5 => 1.0)
flask 0.5 PYSEC-2018-66 0.12.3 Successfully upgraded flask (0.5 => 1.0)
故障排除
您是否解决了 pip-audit
的问题?通过为此部分做出贡献来帮助我们!
pip-audit
显示了无关的漏洞报告!
在一个完美的世界里,漏洞信息源将具有无限的信号与噪声比:每一个漏洞报告都会(1)正确,并且(2)适用于每个依赖项的每一种使用。
不幸的是,这两者都无法保证:漏洞信息源不会免疫于无关或垃圾邮件报告,并且并不是所有特定依赖项的使用都映射到所有潜在类型的漏洞。
如果你的pip-audit
运行产生的漏洞报告对你的特定应用或用例没有可操作性的话,你可以使用--ignore-vuln ID
选项来忽略特定的漏洞报告。--ignore-vuln
支持别名,因此如果你要忽略的报告没有PYSEC ID,你可以使用GHSA-xxx
或CVE-xxx
ID代替PYSEC-xxx
ID。
例如,以下是如何忽略GHSA-w596-4wvx-j9j6的方法,它是pytest
用户常见的高噪声漏洞报告和误报来源,pytest
的GitHub链接:pytest
# Run the audit as normal, but exclude any reports that match GHSA-w596-4wvx-j9j6
$ pip-audit --ignore-vuln GHSA-w596-4wvx-j9j6
--ignore-vuln ID
选项与所有其他依赖项解析和审计选项兼容,这意味着它应该与以requirements风格输入、替代漏洞信息源等方式正确工作。
它可以多次传递,以忽略多个报告
# Run the audit as normal, but exclude any reports that match these IDs
$ pip-audit --ignore-vuln CVE-XXX-YYYY --ignore-vuln CVE-ZZZ-AAAA
pip-audit
运行时间比预期的要长!
根据你如何使用它,pip-audit
可能需要执行自己的依赖项解析,这可能需要的时间大约与pip install
对项目执行的时间相当。请参阅安全模型以了解解释。
你有两种避免依赖项解析的方法:审计预先安装的环境,或确保你的依赖项已经完全解析。
如果你知道你已经完全配置了一个与pip-audit -r requirements.txt
审计相同的环境,你可以简单地重用它
# Note the absence of any "input" arguments, indicating that the environment is used.
$ pip-audit
# Optionally filter out non-local packages, for virtual environments:
$ pip-audit --local
或者,如果你的输入已经完全锁定(可选地包含哈希),你可以告诉pip-audit
跳过依赖项解析,使用--no-deps
(未使用哈希锁定)或--require-hashes
(包含哈希锁定)。
后者等同于pip
的哈希检查模式,并且更受推荐,因为它提供了额外的完整性。
# fails if any dependency is not fully pinned
$ pip-audit --no-deps -r requirements.txt
# fails if any dependency is not fully pinned *or* is missing hashes
$ pip-audit --require-hashes -r requirements.txt
pip-audit
无法对我的第三方索引进行身份验证!
经过身份验证的第三方或私有索引
pip-audit
支持--index-url
和--extra-index-url
来配置替代或补充包索引,就像pip
一样。
当未经过身份验证时,这些索引应该按预期工作。但是,当第三方索引需要身份验证时,pip-audit
在普通pip
之上还有一些额外的限制
- 交互式身份验证不支持。换句话说:
pip-audit
不会提示你输入索引的凭据。 pip
的keyring
身份验证是支持的,但仅限于有限的方式:pip-audit
使用subprocess
keyring提供程序,因为审计发生在隔离的虚拟环境中。subprocess
提供程序反过来又受到额外的限制(如必需的用户名);pip
的文档详细解释了这些。
除此之外,一些第三方索引有必需的、硬编码的用户名。例如,对于Google Artifact registry,硬编码的用户名是oauth2accesstoken
。请参阅#742和pip#11971以获取更多信息。
技巧和窍门
针对pipenv
项目进行运行
pipenv
使用 Pipfile
和 Pipfile.lock
文件来跟踪和冻结依赖项,而不是使用 requirements.txt
文件。然而,pip-audit
无法直接处理 Pipfile[.lock]
文件,但可以将这些文件转换为 pip-audit
可以运行的受支持的 requirements.txt
文件。自 v2022.4.8
起开始,pipenv
内置了将依赖项转换为 requirements.txt
文件的命令。
$ pipenv run pip-audit -r <(pipenv requirements)
抑制 pip-audit
的退出码
pip-audit
故意不支持内部抑制其自己的退出码。
需要抑制失败的 pip-audit
调用的用户可以使用标准的shell惯用语来做到这一点
pip-audit || true
或者,要完全退出
pip-audit || exit 0
退出码也可以被捕获并显式处理
pip-audit
exitcode="${?}"
# do something with ${exitcode}
有关需要处理的潜在代码列表,请参阅退出码。
仅报告可修复的漏洞
在开发工作流程中,您可能希望忽略尚未修复的漏洞,并在发布过程中进行调查。pip-audit
不支持忽略未修复的漏洞。但是,您可以将其输出导出为JSON格式,并对其进行外部处理。例如,如果您想仅在检测到有已知修复版本的漏洞时退出非零代码,您可以使用 jq 进行处理:
test -z "$(pip-audit -r requirements.txt --format=json 2>/dev/null | jq '.dependencies[].vulns[].fix_versions[]')"
使用此方法的简单(且效率低下)的示例是
test -z "$(pip-audit -r requirements.txt --format=json 2>/dev/null | jq '.dependencies[].vulns[].fix_versions[]')" || pip-audit -r requirements.txt
它像往常一样运行 pip-audit
,并且仅在已知漏洞有修复版本时才退出非零代码。
安全模型
本节旨在描述使用 pip-audit
时您可以和必须不做的安全假设。
TL;DR:如果您不会使用 pip install
它,那么您也不应该使用 pip audit
它。
pip-audit
是一个用于审计Python环境中具有已知漏洞的包的工具。“已知漏洞”是指包中的公开报告的错误,如果未纠正,可能会允许恶意行为者执行未预期的操作。
pip-audit
可以通过告诉您何时拥有它们以及如何升级它们来保护您免受已知漏洞的侵害。例如,如果您的环境中包含 somepackage==1.2.3
,则 pip-audit
可以告诉您它需要升级到 1.2.4
。
您可以假设 pip-audit
将尽力解决所有Python依赖项,并且要么完全审计每个依赖项,要么明确声明它跳过了哪些依赖项以及为什么跳过它们。
pip-audit
不是一个静态代码分析器。它分析依赖项树,而不是代码,并且无法保证静态地发生任意的依赖项解析。要了解为什么是这样,请参阅Dustin Ingram的关于Python中依赖项解析的优秀帖子。
因此:您绝对不应该假设 pip-audit
会保护您免受恶意包的侵害。特别是,将 pip-audit -r INPUT
作为 pip-audit
的“更安全”变体是不正确的。从所有目的和意义上讲,pip-audit -r INPUT
功能上等同于 pip install -r INPUT
,并且具有少量非安全隔离,以避免与任何本地环境冲突。
pip-audit
主要是用于Python包的审计工具。您绝对不应该假设 pip-audit
会检测或标记通过Python包暴露的“传递”漏洞,而这些漏洞实际上并非包本身的一部分。例如,pip-audit
的漏洞信息来源不太可能包括对可能被流行的Python包使用的有漏洞的共享库的警告,因为Python包的版本与共享库的版本没有紧密的联系。
许可
pip-audit
采用 Apache 2.0 许可协议。
pip-audit
重用并修改了来自 resolvelib
的示例,该示例采用 ISC 许可协议。
贡献
有关详细信息,请参阅 贡献文档。
行为准则
与该项目互动的所有人应遵守 PSF 行为准则。
项目详情
下载文件
下载适用于您平台文件。如果您不确定选择哪个,请了解有关 安装软件包 的更多信息。
源代码分发
构建分发
pip_audit-2.7.3.tar.gz 的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 08891bbf179bffe478521f150818112bae998424f58bf9285c0078965aef38bc |
|
MD5 | c90612859ab1faa206de61c8fe598d50 |
|
BLAKE2b-256 | 462fd030d0d3a50b776f910dd87dc1d57dd4a27bfad176b85882f463632e4747 |
pip_audit-2.7.3-py3-none-any.whl 的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 46a11faee3323f76adf7987de8171daeb660e8f57d8088cc27fb1c1e5c7747b0 |
|
MD5 | cfcce1ab5431ee547e4a3b4da891da23 |
|
BLAKE2b-256 | 4d4ac908ec8a527698a6539b431d70454e18aef04d4190ff48107ed4d3df99ff |