Safety能快速识别requirements.txt中直接声明的包是否存在已知漏洞,但默认只报“明确被标记为insecure”的版本且不递归检查子依赖;它适合轻量级守门,不适合深度供应链审计。

直接说结论:Safety 能快速识别 requirements.txt 中直接声明的包是否存在已知漏洞,但默认只报“明确被标记为 insecure”的版本,且不递归检查子依赖;它适合轻量级守门,不适合深度供应链审计。
为什么 safety check 不显示 CVE 编号?必须加 --full-report
Safety 默认输出极简,只告诉你“有风险”,不告诉你为什么、影响范围多大、对应哪个 CVE。这在排查和修复时几乎没用。
- 不加
--full-report:只输出类似requests 2.20.0 is vulnerable这种模糊提示 - 加
--full-report:会显示CVE-2023-43665、受影响版本区间(如)、漏洞类型(如 HTTP header injection)、官方修复建议 - 如果你用的是 CI/CD 流水线,漏掉
--full-report就等于白扫——开发人员无法判断是否真要升级、升到哪版
safety 扫描不到 pyproject.toml 或 poetry.lock?先生成 requirements.txt
Safety 只认 requirements.txt,对 pyproject.toml 或 poetry.lock 完全无视。这不是 bug,是设计限制。
- 若项目用 Poetry:运行
poetry export -f requirements.txt --without-hashes > requirements.txt再扫 - 若只有
pyproject.toml(如用 setuptools 或 hatch):不能靠pipreqs——它基于 import 语句推断,会漏掉build-system.requires或project.optional-dependencies里的包;稳妥做法是先用pip install .装一遍,再pip freeze > requirements.txt - 注意:
pip freeze输出的是当前环境所有包,不是项目最小依赖集;生产环境建议始终以 lock 文件为准,再转成 requirements.txt
CI 中 safety 报 ConnectionError 或缓存过期?离线模式 + 清缓存
GitHub Actions 或 GitLab CI 常见失败不是因为漏洞,而是网络或本地缓存问题。
立即学习“Python免费学习笔记(深入)”;
- 无外网权限时:改用离线数据库,命令加
--db https://raw.githubusercontent.com/pyupio/safety-db/master/data/insecure.json - 缓存过期导致漏报:CI 步骤里加
--cache-clear,避免复用开发机上陈旧的~/.cache/safety - 扫描结果非零退出码会中断 pipeline:别用
|| true掩盖问题,改用--fail-on=CRITICAL或--fail-on=MEDIUM精准控制中断阈值 - 安全团队要求“零中危以上”:配置
safety check -r requirements.txt --full-report --fail-on=MEDIUM
insecure 和 unpinned 是两回事,别混淆
很多人看到 unpinned 就以为是漏洞,其实它只是版本未锁定的风险提示,Safety 默认根本不报这个。
-
insecure:该包版本已在safety-db中被标记为含已知漏洞(如Django 存在 XSS) -
unpinned:写的是requests而非requests==2.31.0,下次pip install可能拉到带漏洞的新版——需显式加--ignore-unpinned才触发检查 - 二者修复方式不同:
insecure要升级到安全版本;unpinned要补上==锁死版本,否则 CI 每次构建都可能得到不同结果
真正容易被忽略的是:Safety 的数据库更新有延迟,低危漏洞可能滞后数天;高危漏洞虽几小时内收录,但它不查 NVD 实时数据,也不覆盖 GitHub Advisory 中刚披露的 Python 包漏洞。所以,别把它当唯一防线,pip-audit 或 OSV-Scanner 至少配一个交叉验证。


















