detect-secrets
相关工具推荐
| 工具 | 说明 |
|---|---|
| Gitleaks | Git 仓库密钥泄露检测工具 |
| CodeQL | 语义代码分析平台,支持多语言安全分析 |
| Bandit | Python 安全漏洞扫描工具 |
| Gosec | Go 语言安全检查工具 |
| Pre-commit | Git pre-commit 钩子管理框架 |
1. 简介
detect-secrets 是由 Yelp 开发并开源的企业级密钥泄露检测工具,采用 Apache-2.0 许可证。它专注于在代码仓库中检测和防止敏感信息(如 API 密钥、密码、令牌、私钥等)的意外提交,是 DevSecOps 流程中"安全左移"理念的常见工具之一。
与同类工具(如 Gitleaks、TruffleHog)相比,detect-secrets 的独特之处在于其**基线管理(Baseline)**机制:它承认大型代码库中可能已存在历史遗留的敏感信息,通过建立基线快照来防止新的密钥进入代码库,而非要求一次性清除所有历史问题。这种渐进式策略使其特别适合企业级大规模项目的安全治理。
- 主要检查语言:通用(不限于特定语言)
- 主要检查能力:检测代码仓库中的 API 密钥、密码、令牌、私钥等敏感信息泄露;涵盖密钥泄露检测(Secret Scanning)
- 核心检查原理:插件化检测引擎,基于关键词匹配和熵分析的检测插件,基线管理机制
- 检查规则/选项:内置 27 个检测器插件(如 AWSKeyDetector、Base64HighEntropyString、JwtTokenDetector、PrivateKeyDetector、SlackDetector 等),通过
detect-secrets scan --list-all-plugins查看,检测器说明 - GitHub 仓库:https://github.com/Yelp/detect-secrets(4,545 stars)
- 开源协议:Apache-2.0
- 最新稳定版本:v1.5.0
- 运行环境要求:Python 3.7+
- 误报率:低
2. 官方文档
| 资源 | 链接 | 说明 |
|---|---|---|
| GitHub 仓库(含完整文档) | https://github.com/Yelp/detect-secrets | 源代码、Issue、README、使用说明 |
| GitHub Releases | https://github.com/Yelp/detect-secrets/releases | 版本发布记录 |
| CHANGELOG | CHANGELOG.md | 版本变更详情 |
| 插件文档 | docs/plugins.md | 插件配置、自定义插件开发 |
| 过滤器文档 | docs/filters.md | 内置过滤器、自定义过滤器 |
| 审计文档 | docs/audit.md | 基线审计、报告生成 |
| 设计文档 | docs/design.md | 架构设计说明 |
| PyPI 包页面 | https://pypi.org/project/detect-secrets/ | 安装、版本历史 |
| CONTRIBUTING | CONTRIBUTING.md | 贡献指南 |
快速安装:
# 通过 pip 安装(推荐)
pip install detect-secrets
# 通过 Homebrew 安装(macOS)
brew install detect-secrets
3. 社区优秀实践
3.1 Yelp(工具发起者)
Yelp 作为 detect-secrets 的开发者和主要使用者,在其自身仓库中集成了该工具。Yelp 的 .pre-commit-config.yaml 展示了 detect-secrets 与 pre-commit 框架的深度集成方式,使用 repo: local 配置将 detect-secrets-hook 作为本地钩子运行,并配合 .secrets.baseline 文件管理已知密钥。
- 仓库地址:https://github.com/Yelp/detect-secrets
- 实践特点:使用
repo: local+language: python的 pre-commit 本地钩子模式,在开发者提交代码前自动扫描
3.2 Bridgecrew / Checkov(云安全平台)
Bridgecrew(后被 Palo Alto Networks 收购)维护了 detect-secrets 的一个分支 bc-detect-secrets,在其 Checkov 安全扫描工具中集成了 detect-secrets 的检测能力,为用户提供更全面的 IaC(基础设施即代码)和通用代码密钥扫描。
- 仓库地址:https://github.com/bridgecrewio/checkov
- PyPI 分支:https://pypi.org/project/bc-detect-secrets/
- 实践特点:将 detect-secrets 作为 Checkov 的 secrets 检测后端,扩展了 IaC 场景的覆盖
3.3 pre-commit 官方生态
detect-secrets 是 pre-commit 生态中密钥检测类工具的常见选择之一。其官方仓库自带 .pre-commit-hooks.yaml 定义,可直接被 pre-commit 框架引用,无需额外配置 hook 入口。
- hook 定义文件:
.pre-commit-hooks.yaml - 实践特点:使用
language: python,pre-commit 自动管理 Python 虚拟环境安装 detect-secrets
4. 工具配置说明
以下是一个面向通用项目的推荐配置,重点在于合理调整插件参数和过滤器来优化检测精度。
4.1 配置文件说明
detect-secrets 的核心配置文件是 .secrets.baseline,采用 JSON 格式,由 detect-secrets scan 命令自动生成。
| 配置文件 | 用途 | 使用场景 |
|---|---|---|
.secrets.baseline |
基线快照与扫描配置 | 记录已发现的潜在密钥,同时存储插件和过滤器配置 |
基线文件结构示例:
{
"version": "1.5.0",
"plugins_used": [
{
"name": "AWSKeyDetector"
},
{
"name": "Base64HighEntropyString",
"limit": 4.5
},
{
"name": "HexHighEntropyString",
"limit": 3.0
},
{
"name": "KeywordDetector"
},
{
"name": "PrivateKeyDetector"
}
],
"filters_used": [
{
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
}
],
"results": {},
"exclude_regex": [],
"exclude_files": [],
"automatically_generated_by": true
}
4.2 .secrets.baseline 配置详解
配置项说明:
| 字段 | 类型 | 说明 |
|---|---|---|
version |
string | 生成该基线文件的 detect-secrets 版本号 |
plugins_used |
array | 扫描时启用的插件列表及其配置参数 |
filters_used |
array | 扫描时启用的过滤器列表 |
results |
object | 扫描发现的潜在密钥(按文件分组) |
exclude_regex |
array | 排除的行内容正则表达式 |
exclude_files |
array | 排除的文件路径正则表达式 |
automatically_generated_by |
bool | 是否由工具自动生成 |
推荐配置示例(基线生成命令):
通过调整插件参数来优化检测精度,减少误报:
detect-secrets scan \
--disable-plugin KeywordDetector \
--base64-limit 4.5 \
--hex-limit 3.0 \
--exclude-files 'vendor/.*' \
--exclude-files '.*\.lock$' \
--exclude-files '.*\.svg$' \
--exclude-lines 'password = (blah|fake|test|example)' \
> .secrets.baseline
参数说明:
| 参数 | 说明 |
|---|---|
--disable-plugin KeywordDetector |
禁用关键字检测器(误报率较高,适合初期阶段关闭) |
--base64-limit 4.5 |
Base64 高熵字符串阈值(默认 4.5,值越高越严格) |
--hex-limit 3.0 |
十六进制高熵字符串阈值(默认 3.0) |
--exclude-files |
排除特定文件路径 |
--exclude-lines |
排除匹配特定模式的行 |
4.3 内置插件完整列表
以下为 detect-secrets v1.5.0 内置的所有检测插件(通过 detect-secrets scan --list-all-plugins 查看):
| 插件名称 | 检测目标 | 类型 |
|---|---|---|
ArtifactoryDetector |
JFrog Artifactory API 密钥 | 正则匹配 |
AWSKeyDetector |
AWS Access Key / Secret Key | 正则匹配 |
AzureStorageKeyDetector |
Azure 存储账户密钥 | 正则匹配 |
BasicAuthDetector |
HTTP Basic Auth 凭证 | 正则匹配 |
CloudantDetector |
IBM Cloudant 凭证 | 正则匹配 |
DiscordBotTokenDetector |
Discord Bot Token | 正则匹配 |
GitHubTokenDetector |
GitHub Token | 正则匹配 |
GitLabTokenDetector |
GitLab Token | 正则匹配 |
Base64HighEntropyString |
高熵 Base64 编码字符串 | 熵值分析 |
HexHighEntropyString |
高熵十六进制字符串 | 熵值分析 |
IbmCloudIamDetector |
IBM Cloud IAM 密钥 | 正则匹配 |
IbmCosHmacDetector |
IBM COS HMAC 凭证 | 正则匹配 |
IPPublicDetector |
公网 IP 地址 | 正则匹配 |
JwtTokenDetector |
JSON Web Token | 正则匹配 |
KeywordDetector |
包含 password/secret 等关键字的赋值 | 关键字匹配 |
MailchimpDetector |
Mailchimp API 密钥 | 正则匹配 |
NpmDetector |
NPM 令牌 | 正则匹配 |
OpenAIDetector |
OpenAI API 密钥 | 正则匹配 |
PrivateKeyDetector |
PEM 格式私钥 | 正则匹配 |
PypiTokenDetector |
PyPI / TestPyPI 令牌 | 正则匹配 |
SendGridDetector |
SendGrid API 密钥 | 正则匹配 |
SlackDetector |
Slack Token / Webhook | 正则匹配 |
SoftlayerDetector |
IBM Softlayer 密钥 | 正则匹配 |
SquareOAuthDetector |
Square OAuth 密钥 | 正则匹配 |
StripeDetector |
Stripe API 密钥 | 正则匹配 |
TelegramBotTokenDetector |
Telegram Bot Token | 正则匹配 |
TwilioKeyDetector |
Twilio API 密钥 | 正则匹配 |
4.4 自定义插件示例
detect-secrets 支持通过继承 BasePlugin 或 RegexBasedDetector 基类来开发自定义检测插件(docs/plugins.md -- Writing Your Own Plugin):
# custom_plugins.py
from detect_secrets.plugins.base import RegexBasedDetector
class CompanyApiKeyDetector(RegexBasedDetector):
"""自定义插件:检测公司内部 API Key 格式"""
secret_type = 'Company API Key'
def analyze_string(self, string, line_num, filename):
# 检测公司 API Key 格式:COMPANY_KEY_xxxx
import re
pattern = r'COMPANY_KEY_[A-Za-z0-9]{32}'
match = re.search(pattern, string)
if match:
return {
'type': self.secret_type,
'filename': filename,
'line_number': line_num,
'hashed_secret': self._hash_secret(match.group()),
}
return None
使用自定义插件:
detect-secrets scan --plugin custom_plugins.py test_data
5. 主流集成方式
5.1 pip 安装 + pre-commit 集成(优先推荐)
在开发者执行 git commit 时自动扫描暂存文件。团队仍应在 CI 中维护和校验 baseline,避免只依赖本地钩子。
步骤 1:安装依赖
pip install detect-secrets
pip install pre-commit
步骤 2:创建基线文件
detect-secrets scan > .secrets.baseline
步骤 3:在项目根目录创建 .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ["--baseline", ".secrets.baseline"]
依赖说明:该 hook 使用
language: python,pre-commit 会自动创建独立的 Python 虚拟环境并安装 detect-secrets,无需系统预先安装。files: .*表示匹配所有文件。
步骤 4:安装钩子
pre-commit install
步骤 5:手动运行全量扫描(可选)
pre-commit run --all-files
排除特定文件(如 lock 文件、图片等):
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ["--baseline", ".secrets.baseline"]
exclude: |
(?x)^(
.*\.lock$
| .*\.svg$
| vendor/.*
| node_modules/.*
| \.venv/.*
)
pre-commit 默认只扫描暂存区的文件(staged files),因此不会对未修改的文件产生告警。配合
--baseline参数,仅当新增的密钥不在基线中时才会拦截提交。
增量检查:pre-commit 框架默认仅将暂存区中变更文件传给 detect-secrets hook,天然实现文件级增量检查。配合 --baseline 参数,仅当新增的密钥不在基线中时才会拦截提交。
5.2 IDE 集成
detect-secrets 本身没有官方 IDE 扩展,但可通过以下方式在开发环境中使用:
VS Code -- 通过 pre-commit 扩展自动运行:
安装 pre-commit 扩展后,VS Code 会在提交时自动运行 pre-commit 钩子,包括 detect-secrets 检查。
VS Code -- 通过 Tasks 配置手动触发:
在 .vscode/tasks.json 中添加任务:
{
"version": "2.0.0",
"tasks": [
{
"label": "Scan Secrets",
"type": "shell",
"command": "detect-secrets scan --baseline .secrets.baseline",
"problemMatcher": []
}
]
}
5.3 命令行使用方式
detect-secrets 提供三个核心命令,分别用于不同场景:
| 命令 | 用途 |
|---|---|
detect-secrets scan |
扫描仓库并生成/更新基线文件 |
detect-secrets-hook |
检查文件中是否有不在基线中的新密钥(用于 pre-commit) |
detect-secrets audit |
审计基线文件,标记真/伪阳性,生成报告 |
扫描并生成基线文件:
# 扫描当前 Git 仓库,生成基线文件
detect-secrets scan > .secrets.baseline
# 扫描指定目录(非 Git 跟踪文件)
detect-secrets scan test_data/ --all-files > .secrets.baseline
# 从其他目录扫描
detect-secrets -C /path/to/directory scan > /path/to/directory/.secrets.baseline
更新基线文件:
# 重新扫描并更新基线(保留已标记的条目,添加新发现的密钥)
detect-secrets scan --baseline .secrets.baseline
使用 detect-secrets-hook 检查新密钥:
# 扫描暂存文件(pre-commit 钩子默认行为)
git diff --staged --name-only -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
# 扫描所有 Git 跟踪文件
git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
审计基线文件:
# 交互式审计(逐条标记真/伪阳性)
detect-secrets audit .secrets.baseline
# 生成审计报告
detect-secrets audit --report .secrets.baseline
# 仅输出真实密钥
detect-secrets audit --report --only-real .secrets.baseline
# 查看统计信息(各插件的精确度和召回率)
detect-secrets audit --stats .secrets.baseline
插件管理:
# 查看所有可用插件
detect-secrets scan --list-all-plugins
# 禁用特定插件
detect-secrets scan --disable-plugin KeywordDetector --disable-plugin AWSKeyDetector
# 仅运行特定插件(禁用其他所有插件)
detect-secrets scan --list-all-plugins | \
grep -v 'BasicAuthDetector' | \
sed "s#^#--disable-plugin #g" | \
xargs detect-secrets scan test_data
增量检查 -- detect-secrets 提供两种命令行增量方案:
detect-secrets-hook + git diff 命令行增量方案 -- detect-secrets-hook 命令支持直接传入文件列表:
# 检查暂存区变更文件
detect-secrets-hook --baseline .secrets.baseline $(git diff --name-only --cached)
# 检查相对于 main 分支变更的文件
detect-secrets-hook --baseline .secrets.baseline $(git diff --name-only main...HEAD)
基线比对增量检测 -- 通过对比新旧基线文件,仅获取新增的密钥:
# 1. 生成当前状态的基线
detect-secrets scan > .new-baseline.json
# 2. 审计新基线
detect-secrets audit .new-baseline.json
# 3. 与旧基线比对,获取新增密钥
detect-secrets audit --report .secrets.baseline .new-baseline.json
CI 脚本调用:
GitHub Actions
在 .github/workflows/detect-secrets.yml 中配置:
name: Detect Secrets
on: [push, pull_request]
jobs:
detect-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install detect-secrets
run: pip install detect-secrets
- name: Scan for secrets
run: |
if [ -f .secrets.baseline ]; then
detect-secrets scan --baseline .secrets.baseline --list-all-plugins
else
detect-secrets scan > .secrets.baseline
echo "::warning::No baseline found, created .secrets.baseline"
fi
GitLab CI
在 .gitlab-ci.yml 中添加安全检测阶段:
stages:
- security
detect_secrets:
stage: security
image: python:3.11
before_script:
- pip install detect-secrets
script:
- detect-secrets scan --baseline .secrets.baseline --list-all-plugins
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
增量检查 -- GitHub Actions 中基于 pre-commit 框架的增量检查:
name: Detect Secrets
on: [pull_request]
jobs:
detect-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: pip install pre-commit
- name: Run detect-secrets on changed files
run: pre-commit run detect-secrets --files $(git diff --name-only --diff-filter=ACMR origin/$GITHUB_BASE_REF)
GitLab CI 中仅 MR 时触发增量检查:
detect_secrets:
stage: security
image: python:3.11
before_script:
- pip install detect-secrets
script:
- git diff --name-only --diff-filter=ACMR $CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD | xargs detect-secrets-hook --baseline .secrets.baseline
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
5.4 Python 项目依赖集成
detect-secrets 可作为 Python 项目的开发依赖安装,方便在构建脚本或 Makefile 中调用。
requirements.txt:
detect-secrets>=1.5.0
pyproject.toml(现代 Python 项目):
[project.optional-dependencies]
dev = [
"detect-secrets>=1.5.0",
]
在 Makefile 中集成:
.PHONY: scan-secrets
scan-secrets:
detect-secrets scan --baseline .secrets.baseline
6. 告警抑制(屏蔽)方法
detect-secrets 提供多种告警抑制方式,从粗粒度到细粒度,满足不同场景的需求。
6.1 通过代码注释屏蔽(行内 Allowlisting)
在代码中通过特殊注释直接忽略特定行的密钥检测(官方 README -- Inline Allowlisting):
# 方式一:行尾注释
API_KEY = "sk-1234567890abcdef" # pragma: allowlist secret
// 方式二:下一行注释
// pragma: allowlist nextline secret
const secret = "hunter2";
// 同样适用于 Java 等语言
String password = "test123"; // pragma: allowlist secret
6.2 通过基线文件屏蔽(最常用)
将已知的密钥记录在基线文件中,后续扫描不再对这些密钥告警。这是 detect-secrets 的核心设计理念(官方 README -- Creating a Baseline):
# 首次扫描生成基线(所有已知密钥被记录)
detect-secrets scan > .secrets.baseline
# 后续扫描仅报告新增密钥
detect-secrets scan --baseline .secrets.baseline
6.3 通过审计模式标记为误报
通过交互式审计命令,逐条标记基线中的密钥为"误报"或"真实密钥"(官方 README -- Auditing a Baseline,docs/audit.md):
# 启动交互式审计
detect-secrets audit .secrets.baseline
在交互式审计中,对每条发现可以选择:
| 选项 | 说明 |
|---|---|
y (yes) |
确认是真实的密钥(需要轮换) |
n (no) |
标记为误报(False Positive) |
s (skip) |
跳过当前条目 |
q (quit) |
退出审计 |
6.4 通过工具命令行参数屏蔽
通过命令行参数排除文件、行或密钥模式(官方 README -- scan options):
# 排除特定文件路径
detect-secrets scan --exclude-files 'vendor/.*' --exclude-files '.*\.json$'
# 排除特定行内容
detect-secrets scan --exclude-lines 'password = (blah|fake|test)'
# 排除特定密钥内容
detect-secrets scan --exclude-secrets 'example.*secret'
# 使用词列表排除包含特定词的密钥
detect-secrets scan --word-list wordlist.txt
# 禁用特定插件
detect-secrets scan --disable-plugin KeywordDetector --disable-plugin AWSKeyDetector
# 禁用特定过滤器
detect-secrets scan --disable-filter detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign
6.5 通过工具配置文件屏蔽
基线文件(.secrets.baseline)本身也是配置文件,其中的 plugins_used、filters_used、exclude_files 等字段控制扫描行为(docs/plugins.md -- Configuring Plugins):
{
"version": "1.5.0",
"plugins_used": [
{
"name": "AWSKeyDetector"
},
{
"name": "Base64HighEntropyString",
"limit": 5.0
}
],
"filters_used": [
{
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
}
],
"results": {},
"exclude_files": ["vendor/.*", ".*\\.lock$"]
}
6.6 通过自定义过滤器屏蔽
通过编写自定义过滤器函数来排除特定模式的误报(docs/filters.md -- Using Your Own Filter):
# custom_filter.py
def is_test_secret(secret: str) -> bool:
"""过滤测试用的假密钥"""
test_patterns = ['test', 'example', 'fake', 'placeholder', 'blah']
return any(pattern in secret.lower() for pattern in test_patterns)
使用方式:
detect-secrets scan --filter custom_filter.py::is_test_secret
6.7 通过 pre-commit 框架屏蔽
在 .pre-commit-config.yaml 中通过 hook 级 exclude 限制检查范围:
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ["--baseline", ".secrets.baseline"]
exclude: '^vendor/|^node_modules/|^testdata/|.*\.lock$'