python bandit
说Python Bandit之前先聊聊安全检测这件事儿。平时写代码很多人第一反应是性能和可读性安全问题常常是最后才想起来的东西。打个比方就像装修房子大家忙着选地板颜色、挑沙发样式很少有人会在动工前就把防火报警器的位置都规划好。但问题是等到房子装好了再装报警器线路就得走明线难看不说还容易出问题。Python代码的安全隐患也是这个道理——等到代码都跑在生产环境上了才发现有SQL注入或者硬编码密钥的问题那代价就大了。Bandit就是专门干这个事的工具。它不是那种运行时检测的防护系统而是像给代码做“体检”一样静态地扫描源代码。什么意思呢就是它不需要真正运行你的程序只需要读你的代码文件就能找出潜在的安全风险点。这种设计思路很实际——大部分安全问题其实都出在代码的写法上比如用了不安全的函数、没有做输入校验、把敏感信息写死在代码里。这些东西只要你写了就能被静态分析出来。它能做的事情还挺细致的。举个例子你写了一个用subprocess调用系统命令的模块Bandit会提醒你这个调用是不是拼接了用户输入。哪怕只是os.system(ls filename)这样的写法它也能嗅到危险的味道。再比如你在代码里用了eval或者exec或者pickle.load从不可信来源加载数据这些在Bandit看来都属于高风险操作。它甚至会检查你有没有在requests库的调用里设了verifyFalse禁用SSL证书验证或者用了默认的密钥、硬编码的密码等等。这些东西有时候真的很容易被忽略——尤其是刚开始写代码的时候为了省事直接关了验证后来就忘了改回来。使用起来也很简单。安装只需要pip install bandit然后直接在项目根目录下跑bandit -r .它会递归扫描所有Python文件。默认的输出格式是文本会列出每个问题的严重等级HIGH、MEDIUM、LOW和具体位置。如果觉得输出太冗长可以用-f json输出成JSON格式方便集成到其他工具链。还有一个很贴心的选项是--skip可以跳过某些规则。比如你有一个模块里面不可避免地用了assert在某些场景下assert可能被当作安全隐患因为它可能在优化模式下被跳过但你确认那个模块的逻辑没问题就可以通过--skip B101跳过那个规则B101是assert的检测编号。不过跳过规则的时候最好在项目文档里说明原因不然以后换个人维护代码看到跳过了安全检查心里难免犯嘀咕。说到最佳实践有一些小经验可以分享。首先Bandit应该集成到CI/CD流水线里而不是只在本地跑一跑。道理很简单本地跑完忘记修是常有的事但如果PR合并之前CI就拒绝了那就逼着团队必须处理。通常的做法是在pyproject.toml或者.bandit文件里配置白名单规则和严重度阈值比如只把HIGH级别的当作阻断MEDIUM和LOW的允许通过但记录成警告。其次Bandit的基线文件baseline很有用。如果项目是半路开始使用Bandit一开始肯定会跑出一大堆问题这时候不要一股脑全修完时间不允许可以先生成一个基线文件bandit-baseline.json然后让后续的扫描只报告增量问题。这样团队可以慢慢地、有条理地修复老问题同时新代码绝不带新问题进来。还有一个细节值得一提Bandit对动态代码生成和异步编程的支持有限。比如用了exec动态拼接代码或者大量使用asyncio的高级特性它的静态分析可能会漏报。这时候就需要结合代码审查来做补充不能完全依赖工具。同类工具里比较常见的有Safety、Semgrep和Sourcery。Safety专注在检查Python依赖包的已知漏洞比如某个版本的requests有CVE它会提醒你升级。这和Bandit的定位完全不同——Bandit看的是你写的代码Safety看的是你用的外部包。Semgrep更像一个通用静态分析框架规则可定制性极强你需要什么规则可以自己写但同样学习成本和配置成本也高很多。如果要类比Bandit像是便利店开箱即用常见问题都能覆盖Semgrep像是超市什么都有但需要你自己推着购物车去挑选。Sourcery则偏向代码质量和可维护性比如建议你减少循环嵌套、提取公共代码安全检测只是它功能的一小部分。所以在实际项目中这些工具通常搭配使用Bandit管代码安全Safety管依赖安全Semgrep处理复杂的自定义规则比如检测敏感信息泄露的特定模式形成一道多层的防线。总的来说Bandit不是什么高大上的东西它就是一个老老实实的静态安全扫描工具。它的价值不在于能发现多高深的漏洞——事实上SQL注入、命令注入这些经典问题更多的依赖开发者本身的意识——而在于它能帮你守住一些基础底线。就像开车出门前系安全带大多数人可能一辈子用不上但你知道它在那儿心里就踏实。如果你还没试过可以去翻翻自己项目的代码跑一遍Bandit看看说不定会发现某个角落里躺着一个早就该改掉的小隐患。