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 文件管理已知密钥。

3.2 Bridgecrew / Checkov(云安全平台)

Bridgecrew(后被 Palo Alto Networks 收购)维护了 detect-secrets 的一个分支 bc-detect-secrets,在其 Checkov 安全扫描工具中集成了 detect-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 支持通过继承 BasePluginRegexBasedDetector 基类来开发自定义检测插件(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 Baselinedocs/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_usedfilters_usedexclude_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$'