ECC Python 安全规则实战:环境变量密钥管理与 bandit 静态扫描的分层防护指南
本文围绕 ECC 仓库中面向 Python 开发与审查场景的安全规则文件 .cursor/rules/python-security.md 展开,讲解它在「通用安全规则 → Python 语言安全规则」分层体系中的位置,以及密钥管理、静态安全扫描两大核心命题。读完本文,你将掌握如何在 Python 项目中用环境变量替代硬编码密钥、用 bandit 建立可持续的静态安全扫描闭环,并理解这些规则如何在 ECC 的 python-reviewer Agent 与 /python-review 命令中被自动化执行。
规则文件的定位:Python 安全在 ECC 分层体系中的落点
.cursor/rules/python-security.md 是一份典型的 Agent 规则文件,其 frontmatter 定义了规则的元信息:
description: "Python security extending common rules"
globs: ["**/*.py", "**/*.pyi"]
alwaysApply: false
description开门见山:本文件是对通用安全规则的 Python 化扩展;globs将规则的作用域限定为 Python 源码文件(.py与类型桩文件.pyi);alwaysApply: false结合globs语义,可以推断该规则面向「上下文包含 Python 源文件」的代码生成与审查场景按需生效,而非无差别注入每一次对话。
规则正文第一句点明了它在 ECC 中的层级关系:
This file extends the common security rule with Python specific content.
也就是说,ECC 将安全规则组织为两层:一层是语言无关的通用基线(对应 .cursor/rules/common-security.md,以及规则分发目录 rules/common/security.md),另一层是语言特化扩展(如本文所述的 Python 规则)。这种「common 打底、语言规则叠加」的设计,在仓库中还有一批并行的兄弟规则,例如 .cursor/rules/ 下的 golang-security.md、kotlin-security.md、php-security.md、swift-security.md、typescript-security.md,以及在 rules/python/ 目录下与安全规则并列的 coding-style.md、testing.md、hooks.md、patterns.md、fastapi.md 等配套规则。
值得注意的是,仓库中 Python 安全规则的正文存在两处一致性存放:面向 Cursor harness 的 .cursor/rules/python-security.md(使用 globs 描述作用域)与规则库主目录 rules/python/security.md(使用 paths 描述作用域),正文内容一致,说明同一份规则会被封装适配到不同 Agent harness 使用。
继承的通用底线:提交前的强制安全清单
Python 规则并未自建一套脱离上下文的规范,而是默认叠加上 rules/common/security.md 中约定的、任何代码提交前必须逐项核对的安全清单:
- 不得在代码中硬编码任何秘密(API Key、密码、Token);
- 所有用户输入必须经过校验;
- 通过参数化查询防范 SQL 注入;
- 通过 HTML 净化防范 XSS;
- 开启 CSRF 防护;
- 认证 / 授权逻辑经过验证;
- 所有端点具备限流;
- 错误信息不得泄露敏感数据。
与这份清单呼应,.cursor/rules/common-security.md 进一步给出密钥管理的四条铁律:绝不硬编码、一律使用环境变量或密钥管理器、启动时校验必需密钥存在、对任何可能已暴露的密钥立即轮换。下面的 Python 特化内容正是把这些通用原则落为可执行的代码与命令。
密钥管理:让 API Key 只存在于进程环境中
Python 规则给出的密钥管理示例,是把「环境变量承载秘密 + 启动即校验」落地为两行关键逻辑:
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.environ["OPENAI_API_KEY"] # Raises KeyError if missing
逐行拆解这段代码的安全语义:
from dotenv import load_dotenv:python-dotenv允许本地开发时从一个.env文件把配置注入进程环境,让本地环境与 CI/生产环境统一通过os.environ取值,避免因「本地没有环境变量就跑不起来」而诱使开发者把密钥写死进源码;load_dotenv():将项目根目录的.env文件读入环境,注意它只填充缺失变量,不覆盖进程已有的同名环境变量,因此在部署时由编排平台注入的真实密钥优先级更高;os.environ["OPENAI_API_KEY"]:这里刻意使用下标索引而不是os.environ.get("OPENAI_API_KEY")。下标访问在键缺失时抛出KeyError(代码注释也明确标注了这一行为),实现「fail fast」——如果启动环境中没有配置密钥,程序立即失败,而不是带着None空值继续运行,把错误推迟到真正调用第三方 API 时才暴露。这与通用规则「Validate that required secrets are present at startup(启动时校验必需密钥存在)」的要求完全一致。
.env 文件本身绝不能提交进版本库,应在 .gitignore 中排除,并维护一份不含真实值的 .env.example 作为配置模板供团队拷贝。
对于更复杂的场景,可以引入带默认值与类型转换的读取方式,例如 skills/django-security/SKILL.md 中展示的 django-environ 用法——通过 env('DJANGO_SECRET_KEY') 这类显式读取让缺失配置在配置装载阶段立即报错,同时用 env('DEBUG', default=False, cast=bool) 对可选配置提供受控默认值。这也是把「错误信息不泄露敏感数据」贯彻到配置层的手段之一。
静态安全扫描:用 bandit 建立持续防线
规则要求将 bandit 作为 Python 静态安全分析工具接入日常流程:
bandit -r src/
-r 表示递归扫描 src/ 目录下的所有 Python 文件。bandit 通过 AST 分析在不执行代码的前提下识别高危模式,例如:
- 探测到疑似硬编码的密码 / API Key(
B105、B106、B107等); - 不安全的
eval/exec调用、pickle反序列化、yaml.load; - 使用 MD5 / SHA1 等弱哈希处理安全场景、不安全的随机数生成;
- 拼接式 SQL、
subprocess中直接执行不可信输入等注入类风险。
实际接入 CI 时,可以带上严重级别过滤并让高风险项直接令流水线失败,例如:
# 只报告 HIGH 及以上问题并给出机器可读输出
bandit -r src/ -lll -f json -o bandit-report.json
# 用退出码控制门禁(发现 issue 即非零退出)
bandit -r src/ -q
bandit 在 ECC 中不是孤立建议,它已深度内嵌进仓库的审查工具链,成为可验证的实现事实:
- agents/python-reviewer.md 的「Diagnostic Commands」将
bandit -r .列为与mypy .、ruff check .、black --check .并列的标准诊断步骤,并在 CRITICAL 级安全审查清单中覆盖 SQL/命令注入、路径穿越、eval/exec 滥用、不安全反序列化、硬编码密钥、弱加密、YAML 不安全 load 等 bandit 典型可检出项; - commands/python-review.md 在自动化检查脚本中串联了
bandit -r .、依赖审计pip-audit与safety check,将「静态漏洞扫描」与「依赖供应链风险扫描」合并为一个门禁; - skills/python-patterns/SKILL.md 的 Tooling Integration 一节同样把
bandit -r .作为 Python 工程的必需命令,并与black、isort、ruff、mypy、pytest构成完整工具链。
也就是说,规则的命令只有一句话,但仓库层面的实践把它扩展成了「代码静态分析 → 依赖审计 → 漏洞修复 → 重新扫描」的闭环。
从规则到自动化:审查 Agent 如何执行 Python 安全门禁
规则文件定义了「应当做什么」,而 ECC 把规则翻译成了可自动执行的审查行为。commands/python-review.md 描述的 /python-review 命令流程包含:先通过 git diff 定位改动文件,再运行静态分析工具,随后重点检查 SQL 注入、命令注入、不安全反序列化等安全问题,最后按严重级别输出报告。
Python 审查 Agent agents/python-reviewer.md 给出的 CRITICAL 级安全红线可以直接视为对 python-security 规则的落地解读:
- SQL 注入:查询中拼 f-string → 必须改参数化查询;
- 命令注入:未校验输入进入 shell → 用
subprocess的参数列表形式调用; - 路径穿越:用户可控路径 → 用
normpath校验并拒绝..; - eval/exec 滥用、不安全反序列化、硬编码密钥、弱哈希、
yaml.load不安全加载。
其输出与放行标准构成可复用的门禁模型:
| 状态 | 条件 | 处置 |
|---|---|---|
| PASS | 无 CRITICAL / HIGH 问题 | 允许合入 |
| WARNING | 仅存在 MEDIUM 问题 | 谨慎合入 |
| FAIL | 发现 CRITICAL / HIGH 问题 | 阻塞合入,修复后再过审 |
如果审查中发现安全问题,通用规则还规定了处置协议:立即停止当前工作、转交 security-reviewer Agent(对应 agents/security-reviewer.md)、优先修复 CRITICAL 级问题、轮换可能已暴露的密钥,并对整个代码库复查同类问题。
框架特化与配套资源
python-security 规则的 Reference 一节明确指出:若项目基于 Django,还应参考 django-security 技能获取框架级安全指引。对应仓库实现为 skills/django-security/SKILL.md,其覆盖范围包括生产环境配置(DEBUG = False、安全响应头、HSTS)、SECRET_KEY 强制走环境变量并在缺失时抛出 ImproperlyConfigured、CSRF/XSS/SQL 注入的 ORM 与模板层防护、文件上传校验与限流等。FastAPI 场景的安全要点则散见于 rules/python/fastapi.md 与审查命令中的「CORS 配置、Pydantic 请求校验、响应模型正确性」等专项检查。
此外,Python 工程师还可将安全规则与同一目录下的其余规则配套使用,形成完整覆盖:.cursor/rules/python-coding-style.md 负责 PEP 8 与代码风格、rules/python/testing.md 负责测试纪律、rules/python/patterns.md 负责 Pythonic 模式,而 skills/python-testing/ 提供测试技能层面的支撑。
落地自检清单
将通用与 Python 特化规则汇总为可勾选的提交前自检表:
| 检查项 | 说明 |
|---|---|
| 无硬编码密钥 | 全部敏感值来自 os.environ 或密钥管理器,.env 不入库 |
| 启动即校验 | 用 os.environ["KEY"] 下标访问或配置框架显式声明,缺失立即失败 |
| 静态扫描通过 | bandit -r src/ 无 HIGH 级以上告警 |
| 依赖审计通过 | pip-audit / safety check 无已知漏洞告警 |
| 输入已校验 | 用户输入全部验证,杜绝拼接式 SQL / shell 命令 |
| 泄漏即轮换 | 一旦疑似暴露立即轮换并全库复查同类模式 |
| 框架规则遵循 | Django 项目对照 django-security 技能,FastAPI 项目对照 rules/python/fastapi.md |
安全不是一次性动作,而是持续过程。把通用清单、Python 特化规则、bandit 扫描与 Agent 门禁串成一条自动化链条,才能在每次提交前稳定守住密钥与漏洞两条底线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00