如何开发可集成到CI/CD的Python代码敏感密钥扫描脚本?
Python代码敏感信息扫描脚本实现指南
核心实现思路
- 规则匹配优先:先覆盖常见的敏感字段命名模式,比如API_KEY、SECRET_KEY、PASSWORD、ACCESS_TOKEN、DB_PASS这类变量名,再匹配常见密钥的格式特征,比如AWS AK通常是AKIA开头的20位字符,阿里云AK是LTAI开头,JWT是三段base64用点分隔的字符串
- 排除白名单机制:要提前配置不需要扫描的路径,比如
__pycache__、.git、虚拟环境目录、测试用例文件夹,还要支持代码注释里的# nosecret标记跳过指定行的校验 - 误报过滤:遇到值是环境变量引用(比如
os.getenv("XXX"))、占位符字符串(比如"******"、"xxx")、空值的情况直接跳过,避免无效报错
可直接参考的最小实现示例
import re import os from typing import List, Tuple # 配置规则 SENSITIVE_VAR_PATTERNS = [ re.compile(r'(?i)(api[_-]key|secret[_-]key|password|passwd|db[_-]pass|access[_-]token|auth[_-]token)'), ] SENSITIVE_VALUE_PATTERNS = [ re.compile(r'AKIA[0-9A-Z]{16}'), # AWS AK re.compile(r'LTAI[0-9A-Za-z]{16}'), # 阿里云 AK re.compile(r'^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$'), # JWT ] EXCLUDE_DIRS = {'.git', '__pycache__', 'venv', 'env', 'node_modules'} SKIP_FLAG = '# nosecret' def scan_single_file(file_path: str) -> List[Tuple[int, str]]: """扫描单个Python文件,返回敏感信息的行号和内容""" results = [] with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: for line_num, line_content in enumerate(f, 1): # 跳过标记忽略的行 if SKIP_FLAG in line_content: continue # 匹配敏感变量名,且值不是环境变量/空值/占位符 var_match = any(p.search(line_content) for p in SENSITIVE_VAR_PATTERNS) if var_match: # 过滤合法赋值情况 if 'os.getenv' in line_content or 'os.environ' in line_content: continue if line_content.strip().endswith(('""', "''", 'None', '"***"', "'***'")): continue results.append((line_num, line_content.strip())) continue # 匹配硬编码的密钥格式 value_match = any(p.search(line_content) for p in SENSITIVE_VALUE_PATTERNS) if value_match: results.append((line_num, line_content.strip())) return results def scan_project(root_path: str) -> None: """扫描整个项目目录""" has_sensitive = False for root, dirs, files in os.walk(root_path): # 过滤排除目录 dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: if not file.endswith('.py'): continue file_path = os.path.join(root, file) file_results = scan_single_file(file_path) if file_results: has_sensitive = True print(f"\n发现敏感信息:{file_path}") for line_num, content in file_results: print(f" 第{line_num}行:{content}") if has_sensitive: exit(1) else: print("未检测到敏感信息") exit(0) if __name__ == '__main__': scan_project(os.getcwd())
CI/CD集成适配要点
- 脚本返回值设置:扫描到敏感信息时返回非0状态码,CI/CD流程会自动识别为失败阻断后续步骤
- 结果输出格式化:支持输出json、markdown格式的报告,方便接入CI平台的告警展示
- 增量扫描优化:如果代码仓库很大,可以对接git获取本次提交的变更文件,只扫描变更内容,提升校验速度
优化方向
- 可以引入熵值计算,对随机字符串的熵值做判断,高熵的字符串大概率是密钥,能识别没有明确命名的硬编码密钥
- 支持自定义规则配置,用户可以通过yaml文件新增自己业务相关的敏感字段规则,不需要改代码
- 支持批量忽略历史误报,给每个识别结果生成唯一hash,维护忽略列表直接跳过已知的合法情况
内容的提问来源于stack exchange,提问作者julian_h
相关产品推荐
相关产品推荐

