密钥与敏感信息扫描
本页提供:gitleaks.toml 完整配置(含 AWS Key/GH Token/DB 密码自定义规则)、pre-commit hook 接入、detect-secrets 扫描命令与 baseline 格式、误报 allowlist 写法、密钥泄露后的 5 步 SOP(含命令),以及 GitHub Actions 密钥扫描 workflow 片段。
SKILL 指定扫描范围(含 LFS、子模块、大文件排除)、规则版本与 CI 失败策略;对高熵字符串与已知云厂商密钥模式分优先级处理。
历史提交一旦命中,需评估是否已暴露公网并执行密钥吊销、轮换与审计日志留存;Agent 输出应含建议的应急步骤链接。
gitleaks 完整配置与 pre-commit hook
以下 gitleaks.toml 覆盖 AWS Key、GitHub Token、DB 密码三类自定义规则,同时配置路径排除与误报 allowlist。
# .gitleaks.toml — 版本钉扎 gitleaks v8.x
[extend]
useDefault = true
[[rules]]
id = "aws-access-key-custom"
description = "AWS Access Key ID"
regex = '''(?i)(aws[_\-\. ]?)(access[_\-\. ]?key[_\-\. ]?id|aki)[^a-z0-9]*(=|:|:=)[\s"']*([A-Z0-9]{20})'''
tags = ["key", "aws"]
severity = "critical"
[[rules]]
id = "github-personal-token"
description = "GitHub Personal Access Token (classic or fine-grained)"
regex = '''ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{82}'''
tags = ["token", "github"]
severity = "critical"
[[rules]]
id = "db-password-in-url"
description = "Database password in connection string"
regex = '''(postgres|mysql|mongodb)://[^:]+:([^@\s"']{8,})@'''
tags = ["password", "database"]
secretGroup = 2
severity = "high"
[allowlist]
description = "全局排除:测试 fixture、文档示例"
regexes = [
'''AKIAIOSFODNN7EXAMPLE''',
'''wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY''',
]
paths = [
'''.*_test\.go$''',
'''.*\.md$''',
'''tests/fixtures/.*''',
]
pre-commit hook 配置(.pre-commit-config.yaml)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
args: ["--config=.gitleaks.toml", "--baseline-path=.gitleaks-baseline.json"]
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ["--baseline", ".secrets.baseline"]
exclude: package-lock\.json
- 工具链版本在 CI 中钉扎;子模块与 LFS 指针需显式声明是否纳入。
- 失败策略:真阳性阻塞合并;仅当工单链路与时间盒内的 allowlist 变更才可豁免。
detect-secrets 扫描命令与 baseline 文件
detect-secrets 使用 baseline 文件管理已知误报,新增密钥会让 CI 失败。
# 初始化 baseline(首次运行,将现有误报纳入)
detect-secrets scan --baseline .secrets.baseline \
--exclude-files '\.lock$' \
--exclude-files 'node_modules/'
# 审核新发现(交互式标记误报)
detect-secrets audit .secrets.baseline
# CI 中校验(有新密钥则非零退出)
detect-secrets scan | \
python -c "import sys,json; d=json.load(sys.stdin); sys.exit(1 if d['results'] else 0)"
baseline 文件格式(.secrets.baseline 关键字段)
{
"version": "1.5.0",
"plugins_used": [
{"name": "AWSKeyDetector"},
{"name": "JwtTokenDetector"},
{"name": "KeywordDetector", "keyword_exclude": "example|test|fake|dummy"},
{"name": "HexHighEntropyString", "limit": 3.0},
{"name": "Base64HighEntropyString", "limit": 4.5}
],
"results": {
"config/database.yml": [
{
"type": "Secret Keyword",
"filename": "config/database.yml",
"hashed_secret": "3d20558fe59359...",
"is_verified": false,
"line_number": 12
}
]
},
"generated_at": "2025-01-01T00:00:00Z"
}
误报 allowlist 写法示例
误报通过 allowlist 管理:每条须含匹配原因、责任人、复审周期与可追溯 PR;禁止无注释的全局关闭规则。
# gitleaks.toml — 规则级 allowlist(最小粒度)
[[rules]]
id = "github-personal-token"
# ... 规则定义 ...
[rules.allowlist]
description = "测试 fixture 中使用的占位 token,由安全团队审核 PR#421,复审日 2026-01-01"
regexes = ['''ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''']
paths = ['''tests/fixtures/auth_test\.go$''']
commits = ["abc123def456"] # 仅豁免特定 commit(历史修复)
# gitleaks per-commit inline allowlist(代码行级)
const API_KEY = "test-key-for-unit-tests"; // gitleaks:allow
- 粒度尽量最小:按路径、按规则 ID、或按经审查的正则;避免
*级放行。 - 与代码同库版本化,走审查;到期复审写进条目或工单,防止「永久豁免」。
- 真阳性修复后应删除对应 allowlist 行,而不是保留「已修复」注释占位。
密钥泄露后 SOP(5 步操作流程)与 GitHub Actions 扫描
密钥泄露确认为真阳性后的 5 步应急 SOP:
# 步骤 1:立即吊销密钥(以 AWS 为例)
aws iam delete-access-key --access-key-id AKIAIOSFODNN7ABCDEF
# 步骤 2:检查泄露期间的使用记录
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7ABCDEF \
--start-time $(date -d '30 days ago' --iso-8601) \
--query 'Events[*].{Time:EventTime,Name:EventName,Source:SourceIPAddress}'
# 步骤 3:轮换新密钥(生成 + 写入 Secrets Manager)
NEW_KEY=$(aws iam create-access-key --user-name deploy-bot)
aws secretsmanager put-secret-value \
--secret-id prod/deploy-bot-key \
--secret-string "$NEW_KEY"
# 步骤 4:从 git 历史清除(使用 BFG Repo-Cleaner)
bfg --replace-text secrets-to-remove.txt --no-blob-protection
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push --force --all && git push --force --tags
# 步骤 5:通知 + 留存审计记录
# 在安全工单中记录:泄露时间窗口、影响评估、吊销时间戳、轮换确认
GitHub Actions 密钥扫描 workflow
# .github/workflows/secret-scan.yml
name: Secret Scan
on:
push:
branches: ["main", "develop"]
pull_request:
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 扫描完整历史
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_CONFIG: .gitleaks.toml
GITLEAKS_ENABLE_COMMENTS: true # PR comment 提示
detect-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install detect-secrets==1.5.0
- run: |
detect-secrets scan --baseline .secrets.baseline
git diff --exit-code .secrets.baseline || \
(echo "::error::新密钥被检测到,请运行 detect-secrets audit" && exit 1)
固定顺序:先判定真伪阳性,再决定轮换或 allowlist;历史泄露单独走应急。
[ 本地:pre-commit / push 前扫描 ]
│
▼
[ CI / PR:全树 + 历史(策略内)]
│
┌────────┴────────┐
▼ ▼
[ 规则:厂商模式 ] [ 启发式:高熵 / 泛匹配 ]
│ │
└────────┬────────┘
▼
[ 人工 / Agent triage ]
│
┌────────┴────────┐
▼ ▼
[ 真阳性:轮换 / 吊销 / 审计 ] [ 误报:allowlist 提案 + PR 审计 ]
│ │
└────────┬────────┘
▼
[ 合流:规则版本钉扎 + 报告归档 ]
误报记录模板
下方表单仅在本页浏览器内拼接文本,不上传服务器;用于 PR 描述或安全工单附件。
填写字段后点击「生成」,再「复制」到剪贴板;敏感值请脱敏后粘贴。
SKILL 片段
---
name: secrets-scan-cn
description: 配置 gitleaks/detect-secrets、处理真阳性并规范 allowlist,含密钥泄露 SOP
---
# 步骤
1. 检查 .gitleaks.toml 或等效配置:自定义规则覆盖 AWS/GH/DB 三类密钥
2. 检查 .pre-commit-config.yaml:gitleaks + detect-secrets hook 已配置
3. 检查 .secrets.baseline:存在且已通过 detect-secrets audit
4. CI/CD:secret-scan workflow 在 PR 时运行,fetch-depth=0 扫完整历史
5. allowlist:每条有原因、责任人、复审日期;禁止 * 级全局放行
6. 高熵误报:用路径级排除而非关闭整条规则
7. 真阳性处置:立即吊销 → 查使用记录 → 轮换 → 清历史 → 留审计
8. git 历史清除:使用 bfg 或 git-filter-repo,不能依赖 git reset
9. allowlist 条目到期自动提醒:写入工单或使用 scheduled review
10. 与 SBOM 和依赖扫描告警统一在安全看板展示
# 禁止
- 禁止提交真实密钥到仓库,即使是 private repo
- 禁止使用无注释的全局 allowlist(*)
- 真阳性修复后必须删除 allowlist 条目