一个带来源、经过测试、可离线验证的扫描器,用于检测 OAuth / API 令牌和密钥。每个模式都有来源(主要提供商文档)、经过测试(正样本 + 负样本)且经过验证(兼容 RE2、已检查 ReDoS)。附带一个带置信度分级的 CLI。事实来源是 build_patterns.py 中的 DATA;patterns.json 和本文件均由它生成。
109 个模式 / 64 个提供商 / 生成于 2026-07-02
pip install -e . # console script + importable package
regextokens scan PATH... # walk files/dirs, report findings
regextokens scan PATH -m verified # only offline-proven findings
regextokens scan PATH -f sarif # SARIF for GitHub code scanning
regextokens list # show the catalog
退出状态:0 表示无发现,1 表示存在达到或超过所请求等级的发现,2 表示错误。在 CI 中将其指向 diff 或目录树,以对合并进行门禁控制。默认情况下,输出中的机密信息会被脱敏。
接受已审查的发现(测试夹具、文档示例),使 CI 仅在出现新机密时失败:
regextokens scan . --write-baseline .regextokens-baseline.json # snapshot current findings
regextokens scan . --baseline .regextokens-baseline.json # subtract them
基线存储的是指纹(模式 id 的 sha256 加上哈希后的密钥正文),从不存储密钥本身,因此可以安全提交。匹配与行号无关——在已接受的发现上方进行编辑不会使其取消抑制——但同一令牌出现在不同文件中则属于新的暴露,会被报告。手工编辑的 allow 部分保存策略:fnmatch 路径通配符和模式 id。--write-baseline 会保留并应用它。本仓库提交了自己的基线,覆盖 build_patterns.py 中的合成样本;CI 会针对它进行自扫描。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/odomojuli/regextokens
rev: v0.2.0
hooks:
- id: regextokens
# .github/workflows/secrets.yml
jobs:
secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: odomojuli/regextokens@main
with:
min-confidence: probable
# baseline: .regextokens-baseline.json
# optional: feed the SARIF to code scanning
# - uses: github/codeql-action/upload-sarif@v3
# if: always()
# with: {sarif_file: regextokens.sarif}
两者都默认为 -m probable:low 层级包含公共标识符和占位符,会使提交门禁无法使用。
每个发现都通过离线证明进行评分——仅本地计算,不联网,不调用签发方。形状匹配回答的是*“这看起来像令牌吗?”;这些检查回答的是“我们能否在本地证明它是或不是令牌?”*。使用 -m/--min-confidence 进行过滤。
verified-offline — 校验和或解码器证明结构是真实的(GitHub/npm CRC32;已针对真实已撤销令牌进行经验验证)。probable — 结构加上与真实密钥一致的香农熵主体。low — 仅形状匹配;可能是占位符或公共标识符。rejected — 离线证明表明这可以证明不是真实令牌(例如 CRC32 不匹配);在到达你之前就被丢弃。rejected 层级是差异化所在:一个 ghp_/npm_ 字符串,前缀和长度有效但校验和错误,会被确定性地丢弃,从而消除最高价值提供方中最大的误报类别。离线证明从不声称密钥是有效的——那仍然需要签发方的 API。
pip install pytest
pytest # validate every pattern + engine
python build_patterns.py # regenerate patterns.json + README.md
直接使用目录(无需引擎):
import json, re
pats = json.load(open("patterns.json"))["patterns"]
rx = {p["id"]: re.compile(p["regex"]) for p in pats}
rx["github-pat-classic"].search(text)
build_patterns.py — 唯一数据源(DATA)+ 校验器;重新生成 patterns.json 和 README.md。patterns.json — 生成的目录(机器可读)。切勿手动编辑。regextokens/ — 可安装包:catalog(加载)、scanner(遍历/匹配)、verify(离线验证)、baseline(已接受发现 + 允许列表)、report(人类可读/JSON/SARIF)、cli。内含 patterns.json 的同步副本。.pre-commit-hooks.yaml / action.yml / .github/workflows/ — 分发:pre-commit 钩子、复合 GitHub Action、CI + 标签触发的 PyPI 发布(可信发布)。tests/ — test_patterns.py(每个模式:编译、匹配、RE2、ReDoS)和 test_engine.py(扫描器、验证、报告、CLI、目录同步)。sniffer-audit.md — 对其他密钥扫描器的审计(验证、陈旧性)。references.bib / references.md — 密钥检测文献的参考书目。re。不使用后行断言或反向引用。re.search 编写(扫描嵌入文本)。用 ^/$ 包裹以用作校验器。\b 单词边界括住大多数令牌。如果在 base64 数据块内扫描,请去掉它们。prefix = 单独即可靠;structure = 固定形状;keyword = 依赖附近关键词;identifier = 公开,非密钥;encoding = 格式检查,非密钥。patterns.json 中的示例令牌是合成填充内容,不是真实凭据。sniffer-audit.md — 主要扫描器如何构建和验证模式,附基准数据。references.bib / references.md — 密钥检测文献的参考书目。Base64 字符串 [encoding]
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
格式校验器,而非密钥。标准 Base64 字母表,带填充。锚定。
src: https://datatracker.ietf.org/doc/html/rfc4648#section-4
JSON Web Token (JWT) [structure]
\bey[A-Za-z0-9_-]{10,}\.ey[A-Za-z0-9/_-]{10,}\.[A-Za-z0-9/_-]{10,}
三个 base64url 段。Header 以 ey 开头(即 {“)。解码以检查;仅签名本身不是密钥。
src: https://datatracker.ietf.org/doc/html/rfc7519
PEM 私钥块 [prefix]
-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP |ENCRYPTED )?PRIVATE KEY-----
价值最高的单一指标。匹配任何 PEM 编码私钥的头部行。
src: https://datatracker.ietf.org/doc/html/rfc7468
age X25519 私钥 [structure]
\bAGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}\b
Bech32 使用 HRP 'AGE-SECRET-KEY-';一个 32 字节的密钥在 '1' 分隔符之后编码为 58 个字符(大写)。接收方(age1...)是公开的,不是秘密。后量子变体使用 HRP AGE-SECRET-KEY-PQ-。
src: https://github.com/C2SP/C2SP/blob/main/age.md
认证令牌(已弃用的 API) [structure]
\bamzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b
amzn.mws.。MWS 已退役,由 SP-API 取代(使用 Login with Amazon 令牌,前缀为 Atza|/Atzr|)。原始列表条目格式有误。
src: https://developer-docs.amazon.com/sp-api/docs/migrating-from-amazon-mws
访问密钥 ID [prefix]
\b(?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z2-7]{16}\b
20 个字符。AKIA = 长期 IAM 密钥。ASIA = 临时 STS/会话密钥。主体为 base32(A-Z、2-7)。
src: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html src: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html
秘密访问密钥(关键字门控) [keyword]
(?i)aws[\w.\-= :'\"]{0,25}([A-Za-z0-9/+]{40})
40 字符的 base64 主体没有固定前缀,且熵值较低。需以 'aws' 关键字作为门控条件,否则它会匹配几乎任何 40 字符的 token。
src: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html
API token(关键字门控) [keyword]
(?i)cloudflare[\w.\-= :'\"]{0,25}([A-Za-z0-9_-]{40})
40 字符令牌,无固定前缀;以 'cloudflare' 关键字为门控条件,或匹配任意 40 字符字符串。
src: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
全局 API 密钥(旧版,关键字门控) [keyword]
(?i)cloudflare[\w.\-= :'\"]{0,25}([a-f0-9]{37})
旧版 37 位十六进制全局密钥;受关键字门控。优先使用作用域 API 令牌。
src: https://developers.cloudflare.com/fundamentals/api/get-started/keys/
Origin CA 密钥 [prefix]
\bv1\.0-[0-9a-f]{24}-[0-9a-f]{146}\b
独特的 v1.0- 前缀;正则可靠。
src: https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/
个人访问令牌 [prefix]
\bdop_v1_[0-9a-f]{64}\b
OAuth token dor_v1_ / refresh dor_v1_ 具有相同的结构。
src: https://docs.digitalocean.com/reference/api/create-personal-access-token/
API token / macaroon (fm2_) [prefix]
\bfm2_[A-Za-z0-9+/=]{40,}
Macaroon:先进行 MsgPack 编码,再做 base64 编码,然后前置 fm2_(根据 Fly 自己的仓库,这样做是为了“便于用 grep 查找它们”)。以 FlyV1 fm2_... 形式发送;多个值用逗号连接,每个都带有自己的 fm2_。
src: https://fly.io/docs/security/tokens/ src: https://github.com/superfly/macaroon
API key [prefix]
\bAIza[0-9A-Za-z_-]{35}\b
共 39 个字符。涵盖 Maps、Firebase 以及大多数 GCP API 密钥。
来源:https://cloud.google.com/docs/authentication/api-keys
OAuth 2.0 客户端 ID [prefix]
\b[0-9]+-[0-9a-z]{32}\.apps\.googleusercontent\.com\b
Client ID 是公开的,但会将配置固定到某个项目。以 .apps.googleusercontent.com 结尾。
src: https://developers.google.com/identity/protocols/oauth2
OAuth 2.0 客户端密钥 [prefix]
\bGOCSPX-[0-9A-Za-z_-]{28}\b
当前 client-secret 格式。取代了旧的、无前缀的 24 字符 secret。
src: https://developers.google.com/identity/protocols/oauth2
OAuth 2.0 访问令牌 [prefix]