返回更新列表
新发布Aug 22, 2026

credactor v2.6.0

扫描。修订。提交干净。

分享

PyPI CI License

Credactor

找到密钥。修复它。干净提交。

大多数密钥扫描器止步于告警:你拿到一份泄露凭据的清单,清理工作得自己来做。Credactor 能发现硬编码的密钥并就地重写它们,因此工作区中的泄露只需一条命令即可从发现变为修复。它可以在你的机器上运行,也可以作为 pre-commit 钩子或 CI 门禁运行,并且还能修复 Gitleaks、TruffleHog 或 Betterleaks 发现的问题。

Credactor:扫描、脱敏、干净提交
# Before
db_password = "h8Tq2vKp9mRz4Wd"

# credactor --fix-all .   (default: a sentinel that fails loudly at runtime)
db_password = "REDACTED_BY_CREDACTOR"

# credactor --replace-with env --fix-all .   (read it from the environment)
db_password = os.environ["DB_PASSWORD"]

脱敏会清理你的工作树。 它不会吊销凭据,也不会 触及 git 历史。如果某个密钥曾被提交或共享,请轮换 它,并且如果你需要它从历史中彻底消失,就重写历史(例如使用 git filter-repo)。

为什么选择 Credactor

  • 它会修复,而不只是标记。 每个发现都会就地替换为 哨兵值、你自己的标记,或按文件自身语言进行的环境变量查找。
  • 谨慎写入。 每次编辑都在内存中规划,先备份(模式 0600),写入临时文件,然后重命名到目标位置。运行期间发生变化的文件、 离开扫描根目录的路径,或私钥块会被跳过并给出警告, 其发现仍会被报告。
  • 与你已经在运行的扫描器配合使用。 向它提供 Gitleaks、TruffleHog 或 Betterleaks 报告,它会在一次去重处理中修复它们的发现以及自身的发现。
  • 为流水线而构建。 只读的 --ci 门禁,具有清晰的退出码;SARIF 2.1.0,包含行和列位置,适用于 GitHub Code Scanning;一个 GitHub Action 和一个 pre-commit 钩子。密钥在所有报告格式中都会被掩码,文本 输出会被清理,因此被扫描的文件无法向你的终端或日志注入转义序列或 CI 工作流命令。
  • 发布版本会与其源码进行核对。 纯 Python 3.11+ 标准 库,无运行时依赖。在发布版本进入 PyPI 之前,wheel 和 sdist 中的每个 Credactor 文件都会与带标签的源码逐字节比较,并且包元数据必须与 pyproject.toml 匹配(参见 供应链加固)。

它单独使用并非合适工具的场景:其内置规则覆盖的是最常泄露的 凭据格式,而不是数百个提供商,并且它不会检查密钥是否仍然有效。 一次干净的运行意味着没有匹配到其规则,而不是代码中不包含密钥。请将其与专用扫描器搭配使用 以获得广度(参见 自带扫描器)。

安装

pip install credactor

使用 uv 将其安装为工具,或直接运行一次而无需安装:

uv tool install credactor
uvx credactor --dry-run .

或在 macOS 和 Linux 上使用 Homebrew:

brew install rxb06/tap/credactor

需要 Python 3.11 或更高版本。已在 CI 中于 Linux 和 Windows 上测试,Python 版本为 3.11 至 3.13。对于非 UTF-8、Latin-1 或简单 UTF-16 编码的文件,请添加可选附加项:pip install 'credactor[encoding]' 或 uv tool install 'credactor[encoding]'(Homebrew formula 已包含该附加项)。

快速开始

1. 查看它发现了什么。 不会更改任何内容。

credactor --dry-run .
======================================================================
  CREDENTIAL SCAN REPORT  --  2 finding(s) in 1 file(s)
======================================================================

  FILE: config.py
  ────────────────────────────────────────────────────────────
  Line    3  [HIGH]  [variable:db_password]
           db_password = "h8Tq[REDACTED]"
  Line    4  [CRITICAL]  [pattern:AWS access key]
           aws_key = "AKIA[REDACTED]"

报告仅显示每个密钥的前四个字符。

2. 修复它们。 先审查发现结果:--fix-all 会重写每一个,包括误报。要保留某一个,在其所在行添加 # credactor:ignore(参见抑制误报),或交互式修复并回答 n。在更改每个文件之前,会在其旁边写入一个 .bak 副本,以便你可以撤销。

credactor .                          # ask y/N for each finding (needs a terminal)
credactor --fix-all .                # fix all after one confirmation
credactor --fix-all --yes .          # fix all, no prompt (scripts)
credactor --replace-with env --fix-all .   # environment lookups instead of the sentinel

Env 模式写入的是查找语句,而不是导入语句:如果文件中缺少 import os 或你所使用语言的等价语句,请自行添加。在 Windows Git Bash 上,请以 winpty credactor . 运行交互模式。

3. 检查,然后清理备份。 每个 .bak 文件仍保存着原始密钥,而 Credactor 从不修改你的 .gitignore,因此直接执行 git add . 会将其暂存。

diff config.py.bak config.py         # check what changed
cp config.py.bak config.py           # undo

将 *.bak 和 *.credactor.tmp 添加到 .gitignore,并在你满意后删除备份。若要从一开始就将备份排除在代码树之外,请在修复运行时传入 --secure-backup-dir DIR(一个位于仓库之外的目录)。--secure-delete 则会直接擦除每个备份,这会使 git 成为你唯一的撤销手段。

命令一览

命令作用是否修改文件
credactor --dry-run .报告发现的问题否
credactor .逐条审查并修复发现的问题是,在输入 y 时
credactor --fix-all .在一次确认后修复所有发现的问题是
credactor --ci .门禁:发现问题时以退出码 1 退出从不
credactor --staged --ci .仅对已暂存待提交的内容进行门禁检查从不
credactor --scan-history .扫描最近 100 个更改文件的提交从不
credactor --ci -f sarif . > results.sarif用于 Code Scanning 的 SARIF 2.1.0从不
credactor --ci -f json . > findings.json机器可读的报告从不

所有标志及其组合均见手册。

在 pre-commit 和 CI 中使用

Pre-commit 钩子

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/rxb06/credactor
    rev: v2.7.5
    hooks:
      - id: credactor
pre-commit install

每次 git commit 都会扫描暂存内容,若其中包含凭据则会被阻止。该钩子从不重写文件。它需要 pre-commit 3.2.0 或更高版本;若未使用该框架,请参阅独立钩子。

GitHub Action

steps:
  - uses: actions/checkout@v7
  - uses: rxb06/[email protected]

该 Action 始终以 --ci 运行,因此它绝不会重写检出内容。发现的问题会使该步骤失败,任何错误也会导致失败。若要改为向 Code Scanning 报告而不使步骤失败:

permissions:
  contents: read
  security-events: write

steps:
  - uses: actions/checkout@v7
  - uses: rxb06/[email protected]
    with:
      format: sarif
      upload-sarif: true
      fail-on-findings: false

CI 集成指南 列出了每个 Action 输入和输出,并涵盖 GitLab CI 和纯 shell 步骤。

使用你自己的扫描器

已经在运行 Gitleaks、TruffleHog 或 Betterleaks?把报告交给 Credactor, 它会将它们的发现与自身的发现一起修复,并进行去重(遇到重复项时,保留严重性更高的那个)。与原生扫描一样,先用 --dry-run 预览。

gitleaks dir . -f json -r gl.json
credactor --from-gitleaks gl.json --fix-all --yes .

trufflehog filesystem . --no-verification --json > th.json
credactor --from-trufflehog th.json --fix-all --yes .

betterleaks dir . -f json -r bl.json
credactor --from-betterleaks bl.json --fix-all --yes .

将 Credactor 指向扫描器运行过的同一目录,并在目录树发生变化后重新生成报告。报告以明文保存它发现的每一个密钥,且报告本身不会被扫描(.json 需要 --scan-json),因此请将报告写到仓库之外,或在运行后将其删除。Credactor 无法安全放置的发现项(没有有效的行号、路径位于 .git 下、值太短而无法单独匹配)仍会被报告,但绝不会被写入。详细信息和支持的版本见 Manual。

检测内容

类别示例严重程度
云和 SaaS 密钥AWS(AKIA…、ASIA…)、GCP(AIza…)、Stripe 生产密钥(sk_live_…、rk_live_…)、Slack(xoxb-…、xoxp-…)严重
平台令牌GitHub(ghp_、gho_、ghs_、github_pat_)、GitLab(glpat-)、npm(npm_)、PyPI(pypi-)严重
私钥PEM 块(-----BEGIN … PRIVATE KEY-----,包括加密的)、PGP 私钥块严重
JWTeyJ… 三段式令牌高
连接字符串带内联凭据的 URL(scheme://user:pass@host)高
凭据变量password = "…"、api_key = "…"、secret_key = "…"高、中或低
XML 属性<add key="Password" value="…" />高、中或低
Stripe 测试密钥sk_test_…中
高熵字符串带引号的十六进制(32 到 64 个字符)或 Base64(60 个或更多)中或低

提供商令牌按其格式进行匹配,因此即使在注释中也能被发现,无论其随机性如何。启发式匹配还必须看起来足够随机,而裸的十六进制或 Base64 值只有在被引号括起或被赋值给以凭据命名的变量时才会被报告,这样可以避免误报 git SHA 和校验和。诸如 changeme 之类的占位符、环境变量查找和模板引用不会被标记。

须知:

  • 私钥会被报告,但绝不会被重写。 请轮换密钥并手动删除该块;--fix-all 会将其计为失败。
  • 历史记录是只读且有上限的。 --scan-history 覆盖最近 100 个更改文件的提交,并在仓库有超过 100 个提交时发出警告。
  • 扫描一组固定的文件类型:29 种代码、配置和文本扩展名,加上 .env.* 和 SSH 密钥文件(id_rsa 等)。JSON 需要 --scan-json,其他任何类型需要在 .credactor.toml 中设置 extra_extensions。你直接指定的文件始终会被扫描。
  • 遍历目录时会跳过被 gitignore 的文件,这通常包括本地的 .env。文本报告会列出它们,但 -f json 和 -f sarif 不会提及它们。要检查某个文件,请直接指定它: credactor --dry-run .env。
  • 某些格式原生不在范围内,例如 SendGrid 和 Twilio 密钥以及 Slack webhook,运行时构建的密钥和少于 8 个字符的值也是如此。

完整规则见 Manual, 威胁模型见 Security doc。

重写方式

--replace-with结果适用场景
sentinel(默认)"REDACTED_BY_CREDACTOR"你希望任何仍在使用该密钥的地方大声失败
envos.environ["DB_PASSWORD"]该值应来自环境变量
custom通过 --replacement 指定 "<your marker>"你有自己的约定

分类