安全性检查Python的依赖关系是否存在已知的安全漏洞,并对提出适当的补救措施
作者:Sec-Labs | 发布时间:

Safety 检查 Python 依赖项是否存在已知安全漏洞,并针对检测到的漏洞提出适当的补救措施。 Safety 可以在开发人员机器、CI/CD 管道和生产系统上运行。
默认情况下,它使用开放的 Python 漏洞数据库 Safety DB ,该数据库仅被 许可用于非商业用途 。
对于所有商业项目,Safely 必须升级为使用 PyUp API 使用该 --key 选项。
受支持和测试的 Python 版本
蟒蛇: 3.6 , 3.7 , 3.8 , 3.9 , 3.10 , 3.11
Safety 支持上述版本,但仅在 Python for Actions 提供的最新补丁版本中进行了测试。 例如,在 Python 中, 3.6 我们只会使用 进行测试 3.6.15 ,这是 GitHub 操作上可用的最新 Python 3.6 版本。
确保使用适用于您的 Python 版本的最新补丁。
使用安全作为 GitHub 操作
安全可以作为一项操作集成到您现有的 GitHub CI 管道中。 SAFETY_API_KEY 在 GitHub 上的“设置”->“秘密”->“操作”下设置 您的秘密后,只需将以下内容作为步骤添加到您的工作流 YAML 文件中:
- uses: pyupio/safety@2.3.3
with:
api-key: ${{ secrets.SAFETY_API_KEY }}
(没有 API 密钥?您可以使用 PyUp 注册一个。)
这将在自动检测模式下运行 Safety,该模式会计算出您的项目结构和自动运行的最佳配置。 如果发现任何易受攻击的包,它将使您的 CI 管道失败。
如果你有更复杂的东西,比如 monorepo; 或者在完成测试后,阅读 操作文档 以了解有关将安全配置为操作的更多详细信息。
安装
safety 使用 pip 安装。 请记住,我们仅支持 Python 3.6 及更高版本。
pip install safety
文档
有关详细文档,请参阅 Safety 的文档门户 。
基本用法
要检查您当前选择的虚拟环境是否存在已知安全漏洞的依赖项,请运行:
safety check
你应该得到类似这样的报告:
+=================================================================================+
/$$$$$$ /$$
/$$__ $$ | $$
/$$$$$$$ /$$$$$$ | $$ \__//$$$$$$ /$$$$$$ /$$ /$$
/$$_____/ |____ $$| $$$$ /$$__ $$|_ $$_/ | $$ | $$
| $$$$$$ /$$$$$$$| $$_/ | $$$$$$$$ | $$ | $$ | $$
\____ $$ /$$__ $$| $$ | $$_____/ | $$ /$$| $$ | $$
/$$$$$$$/| $$$$$$$| $$ | $$$$$$$ | $$$$/| $$$$$$$
|_______/ \_______/|__/ \_______/ \___/ \____ $$
/$$ | $$
| $$$$$$/
by pyup.io \______/
+=================================================================================+
REPORT
Safety v2.0.0 is scanning for Vulnerabilities...
Scanning dependencies in your environment:
-> /scanned-path/
Using non-commercial database
Found and scanned 295 packages
Timestamp 2022-06-28 15:42:04
0 vulnerabilities found
0 vulnerabilities ignored
+=================================================================================+
No known security vulnerabilities found.
+=================================================================================+
现在,让我们安装一些不安全的东西:
pip install insecure-package
是的,你真的可以安装它。
再次运行 safety check :
+=================================================================================+
Safety v2.0.0.dev6 is scanning for Vulnerabilities...
Scanning dependencies in your environment:
-> /scanned-path/
Using non-commercial database
Found and scanned 295 packages
Timestamp 2022-06-28 15:42:04
1 vulnerabilities found
0 vulnerabilities ignored
+=================================================================================+
VULNERABILITIES FOUND
+=================================================================================+
-> Vulnerability found in insecure-package version 0.1.0
Vulnerability ID: 25853
Affected spec: <0.2.0
ADVISORY: This is an insecure package with lots of exploitable
security vulnerabilities.
Fixed versions:
PVE-2021-25853
For more information, please visit
https://pyup.io/vulnerabilities/PVE-2021-25853/25853/
Scan was completed.
+=================================================================================+
入门文档
配置扫描目标
Safety 可以扫描 requirements.txt 文件、本地环境以及通过管道传输到 Safety 的直接输入。
要扫描需求文件:
safety check -r requirements.txt
扫描本地环境:
safety check
Safety 还可以从 --stdin 设置了标志的标准输入中读取。
cat requirements.txt | safety check --stdin
或输出 pip freeze :
pip freeze | safety check --stdin
或检查单个包裹:
echo "insecure-package==0.1" | safety check --stdin
有关更多示例,请查看 选项 部分。
指定扫描的输出格式
Safety 可以将扫描结果以多种格式输出。 这包括:屏幕、文本、JSON 和裸输出。 使用 --output 标志配置此输出。 默认输出到屏幕。
--output json 将输出 JSON 以供进一步处理和分析。 --output text 可用于将扫描保存到文件以供以后审核。 --output bare 简单地打印出具有已知漏洞的包
退出代码
默认情况下,Safety 会根据代码的结果发出退出代码,从而允许您在 CI/CD 进程内部运行安全。 如果未发现漏洞,退出代码将为 0。如果发现漏洞,将返回非零退出代码。
扫描基于 Python 的 Docker 镜像
要扫描 docker 图像 IMAGE_TAG ,您可以运行
docker run -it --rm ${IMAGE_TAG} /bin/bash -c "pip install safety && safety check"
在 Docker 中使用安全性
安全可以作为Docker容器轻松执行。 它可以像 示例 部分中描述的那样使用。
echo "insecure-package==0.1" | docker run -i --rm pyupio/safety safety check --stdin
cat requirements.txt | docker run -i --rm pyupio/safety safety check --stdin
使用安全二进制文件
安装后,它们可以像 Safety 的常规命令行版本一样使用。
将安全与 CI 服务结合使用
安全在您的 CI 管道中非常有效。 它默认返回有意义的非零退出代码:
| 代码名称 | 意义 | 价值 |
| --- | :-: | --: |
| EXIT_CODE_OK | 扫描成功 | 0 |
| EXIT_CODE_FAILURE | 发生意外问题,请运行调试模式并写信给我们 | 1个 |
| EXIT_CODE_VULNERABILITIES_FOUND | 安全发现漏洞 | 64 |
| EXIT_CODE_INVALID_API_KEY | 使用的 API KEY 无效 | 65 |
| EXIT_CODE_TOO_MANY_REQUESTS | 您发出的请求过多,请等待 40 秒左右 | 66 |
| EXIT_CODE_UNABLE_TO_LOAD_LOCAL_VULNERABILITY_DB | 本地漏洞数据库格式错误 | 67 |
| EXIT_CODE_UNABLE_TO_FETCH_VULNERABILITY_DB | 尝试获取数据库的客户端网络或服务器问题 | 68 |
| EXIT_CODE_MALFORMED_DB | 获取的漏洞数据库格式错误或在审核命令情况下,要审核的报告格式错误 | 69 |
如果您希望 Safety 在出错时继续(始终返回零退出代码),您可以使用 --continue-on-error 标志
在测试之前或之后运行它。 如果 Safety 发现了什么,您的测试就会失败。
特拉维斯CI
install:
- pip install safety
script:
- safety check
Gitlab CI
safety:
script:
- pip install safety
- safety check
毒素
[tox]
envlist = py37
[testenv]
deps = safety pytest commands = safety check pytest
深度 GitHub 集成
如果您正在寻找与 GitHub 存储库的深度集成:Safety 作为 pyup.io 的一部分提供,称为 Safety CI 。 Safety CI 检查您的提交和拉取请求是否存在已知安全漏洞的依赖项,并在 GitHub 上显示状态。
安全生产
安全是免费和开源的(麻省理工学院许可)。 它所依赖的来自免费 Safety-db 数据库的数据仅限于非商业用途的许可,数量有限且每月仅更新一次。
所有商业项目和团队都必须在 PyUp.io注册付费计划
选项
--key
pyup.io 漏洞数据库的 API 密钥。 这也可以设置为 SAFETY_API_KEY 环境变量。
例子
safety check --key=12345-ABCDEFGH
--db
具有本地漏洞数据库的目录的路径,包括 insecure.json 和 insecure_full.json
例子
safety check --db=/home/safety-db/data
--proxy-host
代理主机 IP 或 DNS
--proxy-port
代理端口号
--proxy-protocol
代理协议(https 或 http)
--output json
以 JSON 格式输出包含漏洞的完整报告。 该报告也可以与审查命令一起使用。
如果您使用的是 PyUp 商业数据库,Safety 将使用相同的 JSON 结构,但包含商业用户的所有完整数据。
例子
safety check --output json
{
"report_meta": {
"scan_target": "environment",
"scanned": [
"/usr/local/lib/python3.9/site-packages"
],
"api_key": false,
"packages_found": 1,
"timestamp": "2022-03-23 01:41:25",
"safety_version": "2.0.0.dev6"
},
"scanned_packages": {
"insecure-package": {
"name": "insecure-package",
"version": "0.1.0"
}
},
"affected_packages": {
"insecure-package": {
"name": "insecure-package",
"version": "0.1.0",
"found": "/usr/local/lib/python3.9/site-packages",
"insecure_versions": [],
"secure_versions": [],
"latest_version_without_known_vulnerabilities": null,
"latest_version": null,
"more_info_url": "None"
}
},
"announcements": [],
"vulnerabilities": [
{
"name": "insecure-package",
"ignored": false,
"reason": "",
"expires": "",
"vulnerable_spec": "<0.2.0",
"all_vulnerable_specs": [
"<0.2.0"
],
"analyzed_version": "0.1.0",
"advisory": "This is an insecure package with lots of exploitable security vulnerabilities.",
"vulnerability_id": "25853",
"is_transitive": false,
"published_date": null,
"fixed_versions": [],
"closest_versions_without_known_vulnerabilities": [],
"resources": [],
"CVE": {
"name": "PVE-2021-25853",
"cvssv2": null,
"cvssv3": null
},
"affected_versions": [],
"more_info_url": "None"
}
],
"ignored_vulnerabilities": [],
"remediations": {
"insecure-package": {
"vulns_found": 1,
"version": "0.1.0",
"recommended": null,
"other_recommended_versions": [],
"more_info_url": "None"
}
}
}
--full-report
完整报告包括安全建议。 它还显示 CVE 的 CVSS 值(需要高级 PyUp 订阅)。
例子
safety check --full-report
--output bare
仅输出易受攻击的包。 与其他工具结合使用很有用。
例子
safety check --output bare
cryptography django
--stdin
从标准输入读取输入。
例子
cat requirements.txt | safety check --stdin
pip freeze | safety check --stdin
echo "insecure-package==0.1" | safety check --stdin
--file , -r
从一个(或多个)需求文件中读取输入。
例子
safety check -r requirements.txt
safety check --file=requirements.txt
safety check -r req_dev.txt -r req_prod.txt
--ignore , -i
通过 ID 忽略一个(或多个)漏洞
例子
safety check -i 1234
safety check --ignore=1234
safety check -i 1234 -i 4567 -i 89101
--output , -o
将报告保存到文件
例子
safety check --output text > insecure_report.txt
safety check --output json > insecure_report.json
审查
如果您以 JSON 格式保存报告,您可以再次以报告格式查看。
选项
--file , -f (必填)
阅读一份不安全的报告。
例子
safety review -f insecure.json
safety review --file=insecure.json
--full-report
完整报告包括安全建议(如果有)。
例子
safety review -r insecure.json --full-report
--bare
仅输出易受攻击的包。
例子
safety review --file report.json --output bare
django
执照
显示包许可证信息(需要高级 PyUp 订阅)。
选项
--key (必需的)
pyup.io 的许可证数据库的 API 密钥。 可以设置为 SAFETY_API_KEY 环境变量。
例子
safety license --key=12345-ABCDEFGH
显示当前环境中每个包的许可证
--output json (可选的)
此许可命令还可以与可选参数结合使用, --output bare 并 --output json 用于可以馈送到其他工具和管道的结构化、可解析的输出。
--db
具有本地许可证数据库的目录的路径 licenses.json
例子
safety license --key=12345-ABCDEFGH --db /home/safety-db/data
--file , -r
从一个(或多个)需求文件中读取输入。
例子
safety license --key=12345-ABCDEFGH -r requirements.txt
safety license --key=12345-ABCDEFGH --file=requirements.txt
safety license --key=12345-ABCDEFGH -r req_dev.txt -r req_prod.txt
--proxy-host , -ph
代理主机 IP 或 DNS
--proxy-port , -pp
代理端口号
--proxy-protocol , -pr
代理协议(https 或 http)
例子
safety license --key=12345-ABCDEFGH -ph 127.0.0.1 -pp 8080 -pr https
Python 2.7
此工具需要从 3.6 版开始的最新 Python 补丁版本。 我们过去确实支持 Python 2.7,但对于其他 Python 3.x 次要版本,它已达到生命周期结束,因此我们无法再支持它。
我们知道您可能仍在运行 Python < 3.6 的项目。 同时,Safety 本身承诺鼓励开发人员保持他们的软件是最新的,我们使用不受官方支持的 Python 版本,甚至是那些已经达到生命周期终点的版本,对我们来说都是没有意义的。
如果您仍然需要从 Python 2.7 环境运行 Safety,请使用 PyPi 提供的 1.8.7 版本。 或者,您可以从 Python 3 环境运行 Safety 来检查 Python 2.7 项目的需求文件。