安全性检查Python的依赖关系是否存在已知的安全漏洞,并对提出适当的补救措施

作者:Sec-Labs | 发布时间:

0c344444d7000915

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 二进制文件 提供了一些 额外的安全性

安装后,它们可以像 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.jsoninsecure_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 项目的需求文件。

标签:工具分享