Files
csctalon/.gitleaks.toml
tanzk 105955e94a ci(#211): ruff 门禁扩 app/ + 新增空库 alembic upgrade head + gitleaks 收窄
- ruff: tests/ -> app/ tests/;清零 app/ 存量 6 处(isort×4 + unused import×2),
  并修复合并扫描才暴露的 tests/test_llm_outage_event 多余空行
- CI(test.yml): 新增独立空库 ci-pg-mig(POSTGRES_DB=csctalon_dev) 上的
  alembic upgrade head + heads 门禁;连接参数用命令级 env 前缀,不污染
  conftest 以 setdefault 从 TEST_POSTGRES_* 回填的 pytest 连接
- 修复真实迁移链断裂: a1c2e3f4d5b6 无条件 DROP CONSTRAINT uq_cs_record_business
  在全新空库报 UndefinedObject(该约束建表迁移从未创建,仅由 create_all 带出)。
  改为先查 pg_constraint 存在才 DROP,空库/存量两路径最终 schema 一致
- gitleaks 收窄: workflows 由 .* 通配收窄为仅精确放行 test.yml;backend/tests
  由"整目录全规则免疫"收窄为仅 hardcoded-phone-number/hardcoded-strong-password
  两条夹具启发式的规则级豁免,内置密钥规则与 scrm/shanmao 业务凭证规则对 tests
  仍全量生效(正/负向实测验证)
- 文档: alembic-migration 规范升 v1.2,增空库可重放门禁(§八-6)与"修复可重放性
  缺陷可改已提交迁移"例外(§八-7);README 记录本地门禁命令

Refs #211
2026-10-07 21:38:07 +08:00

114 lines
5.3 KiB
TOML

# gitleaks 凭证扫描配置
# 用途: 提交前/CI 扫描,防止手机号、密码、OpenAPI ClientId/Secret 等凭证再次硬编码入库
# 运行: gitleaks detect --source . --config .gitleaks.toml --redact
# 预提交钩子: 见 scripts/install-gitleaks-hook.sh
title = "csctalon 自定义凭证扫描"
[extend]
# 继承 gitleaks 内置规则(覆盖常见密钥格式: AKIA/openai/strip/jwt 等)
useDefault = true
# ---------- 全局白名单 ----------
[allowlist]
description = "允许的路径/示例值"
# 注意: 不再整体放行 docs/*.md —— 处置手册等文档必须被扫描,
# 防止把真实凭证当示例写进文档再次入库。文档中只允许出现占位符。
paths = [
'''^\.env\.example$''',
'''^backend/\.env\.example$''',
'''^\.gitleaks\.toml$''',
'''package-lock\.json$''',
'''yarn\.lock$''',
# CI 工作流: 仅 test.yml 含 postgres service 测试口令(非业务凭证, 与 config.py
# 默认一致), 只用于 CI 隔离库, 生产走 .env 注入; 属测试基础设施豁免, 不违反 OPS-11。
# #211 收窄: 不再用 .*\.yml 整体放行整个 workflows 目录 —— 其余 workflow 及未来
# 新增工作流一律纳入扫描, 防凭证借 CI 文件绕过。
'''^\.gitea/workflows/test\.yml$''',
# #211 收窄: 不再整体放行 backend/tests(原放行会让真实密钥借测试文件绕过**所有**规则)。
# 测试夹具天然高发的「假手机号 / 假强密码串」改在对应**规则级** allowlist 精确豁免
# (见文末 hardcoded-phone-number / hardcoded-strong-password 两条规则);
# 而 scrm-* / shanmao-* 业务凭证规则与 gitleaks 内置密钥规则(AKIA/openai/jwt/
# generic-api-key/private-key 等)对 backend/tests 仍全量生效。
]
# 占位符/示例值不报警
# 注意: admin123/csctalon123 已从全局 allowlist 移除(2026-08-20 审计 OPS-11):
# - .env.example 中的默认值已由上方 paths allowlist 覆盖;
# - 业务代码/脚本里再出现这些弱口令必须被扫描报警, 不允许静默放行。
regexes = [
'''<请修改.*>''',
'''<真实.*>''',
'''REDACTED_''',
'''CHANGE_ME_IN_PRODUCTION''',
'''REPLACE_''',
]
# ---------- 自定义规则 ----------
# 规则1: SCRM 白音平台手机号(11位 1开头) + 密码成对出现
[[rules]]
id = "scrm-baiyin-credentials"
description = "SCRM 白音平台登录凭证(手机号+密码)"
regex = '''(?i)(SCRM_WEB_USERNAME|PW_USERNAME|web_username)\s*[:=]\s*["']?1\d{10}["']?'''
tags = ["scrm", "phone", "credential"]
[[rules]]
id = "scrm-openapi-client-secret"
description = "SCRM OpenAPI ClientId/ClientSecret(32位十六进制大写)"
regex = '''(?i)(SCRM_CLIENT_(ID|SECRET)|OPENAPI_CLIENT_(ID|SECRET))\s*[:=]\s*["']?[A-Za-z0-9]{30,}["']?'''
tags = ["scrm", "openapi", "credential"]
# 规则2: 看似真实的明文密码(含特殊符号的强密码模式,排除纯占位符)
[[rules]]
id = "hardcoded-strong-password"
description = "疑似硬编码强密码(字母+数字+特殊符号)"
# 值首字符不为 < : 排除 <密码>/<ClientSecret> 等占位符(真实密码极少以 < 开头)
regex = '''(?i)(password|passwd|pwd|secret)\s*[:=]\s*["'][^"'<][^"']{7,}["']'''
# 排除明显占位
# 注意1: 规则内 allowlist 覆盖全局 allowlist, REDACTED 须在此重复声明,
# 否则 filter-repo 替换后的历史占位(如 PW_PASSWORD="REDACTED_PASSWORD")会被误报
# 注意2: regexTarget=line 使 allowlist 对整行做子串匹配(默认仅匹配行首),
# 否则 `webServer.password = "REPLACE_FRP_DASH_PWD"` 这类模板占位行无法被放行
[rules.allowlist]
regexTarget = "line"
regexes = [
'''<.*>''',
'''CHANGE_ME''',
'''example''',
'''your[_-]?password''',
'''请修改''',
'''REDACTED''',
'''REPLACE_''',
'''\$\{2:?''',
]
# #211: 测试夹具的默认假密码/密文样例(如 pwd="P@ssw0rd123"、
# "unit-test-...-secret"、"sk-...-never-leak")是本条启发式规则的高假阳性来源,
# 故仅此一条规则对 tests 豁免; 真实密钥形态仍由 gitleaks 内置规则在 tests 中扫描。
paths = [
'''^backend/tests/.*\.py$''',
]
tags = ["password", "hardcoded"]
# 规则3: 硬编码管理员手机号(11位连续数字,出现在赋值/字典字面量中)
[[rules]]
id = "hardcoded-phone-number"
description = "疑似硬编码手机号(11位 1开头)"
regex = '''["']?(1[3-9]\d{9})["']?\s*[,\)#]'''
tags = ["phone", "pii"]
# #211: 测试夹具大量构造 11 位手机号(连续假号 13700137xxx、号码分割逻辑样例等),
# 是本条 PII 启发式规则的高假阳性来源, 仅此规则对 tests 豁免; 带账号登录语义的
# SCRM 手机号仍由 scrm-baiyin-credentials 规则(对 tests 生效)兜底, 不会漏。
[rules.allowlist]
paths = [
'''^backend/tests/.*\.py$''',
]
# 规则4: 杉猫(BMS)平台凭证(2026-08-20 审计 C-1 新增)
# 覆盖两种形态: SHANMAO_PASS = "值" 直接赋值, 与 os.environ.get("SHANMAO_PASS", "值") 回退默认值
# 值需非空、非占位符(<开头)、至少 2 字符, 避免误报 .env.example 的空值占位
[[rules]]
id = "shanmao-platform-credentials"
description = "杉猫平台账号密码(含 os.environ.get 回退默认值形态)"
regex = '''(?i)SHANMAO_(?:USER|PASS|PASSWORD|USERNAME)\s*[=:]\s*["'][^"'\s<][^"']*["']|SHANMAO_(?:USER|PASS|PASSWORD|USERNAME)["']\s*,\s*["'][^"'\s<][^"']*["']'''
tags = ["shanmao", "bms", "credential"]