Lercas/prowl

GitHub: Lercas/prowl

Prowl 是一款融合正则规则与 ML 语义分析的多源密钥扫描器,旨在以高召回率和可控误报率检测代码、日志、工单、容器镜像和 Web 应用中的泄露凭据。

Stars: 0 | Forks: 0

Prowl

English · Русский

在代码、git 历史、工单、日志、容器镜像以及已发布的 Web 应用中查找泄露的凭据——涵盖结构化 token 和多语言文本,并提供可选的实时验证。

install go version license last commit stars

Prowl 是一款密钥扫描器。它可以读取代码库、git 历史、在线 Web 页面或文本流,并报告他人遗留的凭据(API keys、token、数据库 URI、散文中的私钥和密码),提供具体的行号、列号及置信度。其目标是**实现高召回率,同时不让您被误报所淹没。** 大多数扫描器迫使您做出选择。正则表达式工具(gitleaks、trufflehog)对结构化 token 的识别非常精确,但会漏掉任何没有固定前缀的内容;ML/语义工具(deepsecrets)能够阅读自由文本,但在处理结构化密钥时却会失效。Prowl 将两者作为一个流水线一起运行——对结构化 token 使用正则/校验和精度,对前缀工具遗漏的多语言文本使用 ML 阶段,并在此基础上提供可选的实时验证。它并不声称是所有工具中误报率最低的(像 gitleaks 这样调优过的前缀扫描器在纯代码环境中可能会更安静);它的目标是在可用的精度下实现最广泛的、真实的覆盖范围。请参阅[基准测试](#benchmark)以获取可复现的数据,以及了解每个工具在哪些方面更具优势。 ``` $ prowl scan . src/config/prod.ts ✖ critical aws_access_key_id 42:18 AKIA••••DSYP live .env.example ✖ high github_pat 3:11 ghp_••••a1b2 docs/onboarding.md ⚠ medium generic_password 88:24 Welc••••e! 71% 3 findings 1 critical · 1 high · 1 medium in 3 files ``` 扫描结果按文件分组(最严重的排在最前),根据严重程度进行着色,并对密钥进行掩码处理。只需一个标志即可输出 JSON(`--format json`)、SARIF(`--format sarif`,用于 GitHub/GitLab 的 Security 标签页)和 DefectDojo(`--format defectdojo`,用于直接上传的 Generic Findings Import)格式。 ## 安装 ``` # Homebrew brew install Lercas/tap/prowl # Go go install github.com/Lercas/prowl/tool/cmd/prowl@latest # Docker docker run --rm -v "$PWD:/src" ghcr.io/lercas/prowl scan /src # 二进制文件 - 从 GitHub Releases 页面下载 (linux/macos/windows, amd64/arm64) ``` ### Pre-commit 将 Prowl 接入 [pre-commit](https://pre-commit.com) —— 就像您接入 gitleaks 的方式一样: ``` # .pre-commit-config.yaml repos: - repo: https://github.com/Lercas/prowl rev: v1.0.0 hooks: - id: prowl # builds from source (needs Go), or: # - id: prowl-docker # no Go toolchain, uses the published image ``` 从 gitleaks 迁移无需重写:`.gitleaks.toml` 会被自动加载,您的 `.gitleaksignore` 会继续屏蔽相同的扫描结果,并且 `gitleaks:allow` 注释也会被保留。运行 `prowl compare` 可以在您切换之前,查看 Prowl 的 ML 阶段将您当前的多少扫描结果标记为噪声。 ## 快速开始 ``` prowl scan . # scan the working tree prowl scan . --staged # only what's staged (pre-commit) prowl scan . --since HEAD~50 # only the last 50 commits' diffs prowl scan . --verify # confirm each hit against the provider's API prowl scan . --format sarif -o out.sarif # for code scanning / CI prowl repo https://github.com/org/repo # clone a remote repo (GitHub/GitLab/Bitbucket) and scan it GITHUB_TOKEN=... prowl org github:my-org # scan every repo in an org/group/workspace prowl image alpine:latest # pull & scan a container image (every layer + config) prowl bucket s3://my-logs/2026/ # download & scan an S3 / GCS prefix (uses your aws/gcloud CLI) kubectl get secret x -o yaml | prowl scan - # scan piped input from stdin prowl domain https://example.com --authorized # HTML, JS bundles, source maps, __NEXT_DATA__ prowl serve # stateless HTTP worker: POST /scan (cascade + rule templates; no in-process ML/verify) ``` 首次运行会安装规则和验证器库;之后它们将自动加载: ``` prowl rules update # fetch + validate + install ~/.prowl/rules prowl verifiers update # fetch + validate + install ~/.prowl/verifiers prowl version # binary + installed library versions ``` ### 减少噪声 无需修改配置文件即可修剪扫描报告的内容。这些过滤器在报告时运行,作用于内置和模板发现的结果: ``` prowl scan . --min-severity high # only high+ findings prowl scan . --min-confidence 0.7 # drop weak, low-confidence guesses prowl scan . --disable generic_high_entropy # silence one noisy detector type prowl scan . --no-dedupe # show every occurrence (default: one per file) ``` 默认情况下,在一个文件中重复发现的相同密钥只会报告一次;使用 `--no-dedupe` 可显示所有结果。[文档](wiki/Scanning-Files.md#cutting-noise) 有关每个命令、标志和功能的完整参考,请查阅 [wiki](wiki/README.md)。 ## 可扫描内容 一个扫描器,多种来源 —— 每一个都运行相同的检测流水线和相同的标志: - **目录或文件** - `prowl scan [path...]`,遍历文件系统。[文档](wiki/Scanning-Files.md) - **stdin** - `prowl scan -`,直接将日志、命令输出或渲染好的 manifest 通过管道输入。[文档](wiki/Scanning-Files.md) - **Git** - 暂存文件(`--staged`)、diff(`--since `)或历史记录中的每个 blob(`--history`)。[文档](wiki/Scanning-Files.md) - **远程仓库** - `prowl repo `,克隆并扫描任何 GitHub/GitLab/Bitbucket/自托管的 URL。[文档](wiki/Repository-Scanning.md) - **整个组织 / 群组 / 工作空间** - `prowl org :`,一次性扫描所有仓库。[文档](wiki/Org-Scanning.md) - **容器镜像** - `prowl image `,拉取并扫描每一层及镜像配置,无需 daemon。[文档](wiki/Container-Scanning.md) - **S3 / GCS 前缀** - `prowl bucket `,通过您的 aws/gcloud CLI 下载并扫描。[文档](wiki/Bucket-Scanning.md) - **在线域名** - `prowl domain --authorized`,扫描 HTML + 内联状态 blob + 引用的 JS 及 source maps。[文档](wiki/Domain-Scanning.md) ## 为什么选择 Prowl - **精度优先。** 一个三阶段流水线(regex + 校验和 + 熵,接着是上下文模型,最后是深度编码器),具有示例/占位符过滤、哈希拒绝和每次发现的单独置信度。在下面的基准测试中,单凭该流水线就获得了所有工具中最高的精度;而 ML 阶段则以少量的精度损失换取了顶级的召回率和领先的 F1 分数。 - **发现正则表达式无法捕捉的内容。** 德语/法语/俄语文本中的密码、没有固定前缀的 token、隐藏在 base64 blob 和 JS source maps 中的密钥。 - **实时验证。** `--verify` 会调用提供商自身的只读身份验证端点(AWS、GitHub、Stripe、GCP、Yandex Cloud 等),并报告哪些密钥当前是真实有效的。这是最强有力的误报过滤器。 - **规则独立于二进制文件之外。** 159 个 YAML 规则文件,您可以编辑、禁用或扩展,并且您现有的 **gitleaks** `.toml` 和 **trufflehog** `.yaml` 规则集可以直接原样使用。 - **快速。** 单线程约 310 MB/s,零分配热路径,跨核心线性扩展。Aho-Corasick 预过滤器意味着 159 条规则的库几乎不会产生额外开销。 - **专为流水线构建。** CLI、pre-commit、GitHub Action、SARIF 输出、退出码控制、用于编辑器高亮的 LSP 模式,以及用于水平扩展的 `serve` 模式。 ## 基准测试 [ProwlBench](https://github.com/Lercas/prowlbench) 是一个包含 24,603 个用例(16,552 个正样本 / 8,051 个负样本)的防泄露基准测试,涵盖结构化 token、通用高熵密钥、多语言自由文本(8 种语言),以及在代码、Jira、Confluence、Slack 和日志中的对抗性硬负样本(哈希、JWT 形态的非 token、SSH 公钥、占位符、localhost DSN、`${ENV}` 引用)。**下表是发布在 [ProwlBench](https://github.com/Lercas/prowlbench) 仓库中排行榜的真实渲染结果;可使用该仓库的 `python -m benchmark.run_prowlbench` 进行复现。** 每个工具都作为真实的子进程运行;测试用例与训练数据互斥。 | 工具 | 精度 | 召回率 | F1 | 准确率 | |------|:--:|:--:|:--:|:--:| | **Prowl** (发布的 Go binary,流水线) | **0.951** | **0.823** | **0.883** | **0.853** | | detect-secrets | 0.848 | 0.423 | 0.564 | 0.561 | | gitleaks | 0.931 | 0.413 | 0.573 | 0.585 | | deepsecrets | 0.921 | 0.309 | 0.462 | 0.517 | | trufflehog | 0.940 | 0.303 | 0.458 | 0.518 | 发布的单个 Go binary —— 流水线(regex + 校验和 + 熵,无需额外部署)—— 在此处的 F1 指标上领先。 **客观解读:** 基准测试中 57% 的正样本是多语言文本中的通用密码/密钥,gitleaks(前缀正则表达式)和 trufflehog(提供商验证器)在设计上并未将其作为目标——在以结构化 token 为主的分布中,召回率的差距会急剧缩小(具体分层数据见 [ProwlBench](https://github.com/Lercas/prowlbench) 的数据表)。Prowl 真实且具体的优势在于多语言文本的召回率,而不是全行业范围内 F1 分数的全面碾压。 ### 独立的跨工具检查 第二项刻意**不加美化**的检查针对所有其他工具的当前版本运行(gitleaks 8.30, trufflehog 3.95, detect-secrets 1.5, deepsecrets 2.0)。学术界的 [SecretBench](https://github.com/setu1421/SecretBench) 语料库受限于 Google BigQuery 的访问权限,因此这里使用了两个可复现的本地数据集:**(A)** 跨越 17 个提供商的 34 个真实格式提供商密钥 + 12 个棘手但干净的文件(UUID/哈希/base64/占位符),以及 **(B)** 一个真实、干净的 OSS 仓库 ([`psf/requests`](https://github.com/psf/requests),157 个文件),其中每一项发现结果都是潜在的误报。每个工具的输入相同;以文件为粒度进行评分;`trufflehog --no-verification`(不会有任何数据离开本地环境)。 | 工具 | (A) 精度 | (A) 召回率 | (A) F1 | (B) 在干净代码上的发现数 | |------|:--:|:--:|:--:|:--:| | gitleaks | 1.00 | 0.94 | **0.97** | **4** ← 最干净 | | **Prowl** `--ml` | 1.00 | 1.00 | 1.00\* | **9** | | detect-secrets | 0.89 | 0.94 | 0.91 | 15 | | **Prowl**(仅流水线) | 1.00 | 1.00 | 1.00\* | 18(在修复资产/表达式 FP 误报之前为 50) | | deepsecrets | 0.96 | 0.71 | 0.81 | 22 | | trufflehog | 1.00 | 0.65 | 0.79 | 34 | **客观解读此表 - Prowl 并非绝对的赢家:** - **\* 数据集 (A) 偏向于 Prowl**(我生成了这些密钥格式,因此它部分衡量的是“Prowl 能否检测出 Prowl 形态的密钥”)。完美的 1.00 是一种假象,而非证明。(A) 中公平的参考信号仅在于*覆盖范围*:Prowl + detect-secrets 覆盖了最多的提供商;trufflehog/deepsecrets 漏掉了它们没有规则支持的提供商(这是覆盖范围的差距,而不是质量更低)。 - **在真实的干净代码 (B) 上,gitleaks 是最干净的(4 个误报),也是总体上最强的工具。** Prowl 的零依赖流水线报告了 18 个误报(在此版本收紧资产/表达式 FP 误报修复之前为 50);其 **ML L2 过滤器(`--ml`,需要 cgo 构建或 sidecar)将其降至 9**,同时没有漏掉 34 个语料库正样本中的任何一个——这就是“我们是否用 ML 来清理 FP 误报?”的答案:是的,清除了流水线一半的剩余噪声,召回率保持不变(L2 是基于从真实干净仓库中挖掘出的硬负样本重新训练的,并在留出的真实数据集上进行了验证——而不是合成数据)。即便如此,Prowl 在真实代码上的误报仍约为 gitleaks 的 2 倍。Prowl 用真实代码上的精度换取了更广泛的提供商覆盖范围和实时验证;如果您想要没有 ML、噪声最低的纯正则扫描器,gitleaks 是更好的选择。 该基准测试是可复现的;语料库生成器和各工具的评分器都是简单的脚本(如果您希望将其上游化,可以索取)。 ## 工作原理

Prowl's three-stage cascade: regex/checksum/entropy, then a text model, then an encoder, combined by union

- **阶段 1,流水线 (Go)。** 由字面关键词锚定的按类型划分的正则表达式,由 Aho-Corasick 预过滤器进行门控,接着是校验和(Luhn、GitHub CRC、JWT 结构)、Shannon 熵和行上下文线索。过滤掉示例、占位符、哈希和公钥材料。此阶段包含在二进制程序中,不需要其他任何依赖。 - **阶段 2,文本模型。** 一个字符 + 单词 TF-IDF 逻辑回归,用于识别正则表达式未能锚定的通用和多语言密码。 - **阶段 3,编码器。** 一个微调过的多语言 transformer ([在 Hugging Face 上](#model--data)),用于处理自由格式和代码内尾部内容。此阶段为可选;流水线在没有它的情况下也能运行。 这三者作为一个并集结合在一起:任何阶段有信心的发现都会成为一个扫描结果,并按位置进行去重。 **运行 ML 阶段。** 阶段 1(流水线)包含在每个二进制文件中,不需要任何依赖。ML 阶段默认不运行。进程内模型(`--ml`)仅在 **cgo build** 时编译进去;静态发布的二进制文件(Homebrew/Docker/Releases,`CGO_ENABLED=0`)会拒绝 `--ml` 并提示您使用 `--ml-url` 或从源代码构建。要在不进行 cgo 构建的情况下运行 ML 阶段,请将模型作为 sidecar 托管并传入 `--ml-url`。简而言之:已发布的二进制文件默认运行流水线(通过 `--ml-url` 使用 ML),而带 cgo 的源码构建则在进程内运行 `--ml`。 ## 规则和验证器 检测规则是简单的模板,每个提供商对应一个 YAML 文件,通过 AND/OR 组合 `word` + `regex` + `entropy` 匹配器: ``` id: stripe-secret-key info: name: Stripe Secret Key severity: critical tags: stripe,payment,credentials matchers-condition: and matchers: - type: word words: ["sk_live_"] - type: regex regex: ['\bsk_live_[0-9a-zA-Z]{24,}\b'] ``` 验证器也是数据驱动的:向提供商的身份端点发送 HTTP 请求,并在响应上使用条件匹配器,配备了一个可插拔的签名系统(AWS SigV4、bearer、basic)。AppSec 团队无需接触 Go 代码即可添加新的检测和验证。参见 [`rules/SCHEMA.md`](tool/rules/SCHEMA.md) 和 [`verifiers/SCHEMA.md`](tool/verifiers/SCHEMA.md),或者 使用 `rules/PROMPT.md` 中的提示词生成一个。 ``` prowl scan . --rules gitleaks.toml --rules trufflehog.yaml # bring your own prowl rules list --tags aws,stripe # browse the library by category prowl rules show stripe-secret-key # one rule's matchers + reference prowl rules test 'key = "sk_live_4eC39HqLyjWD..."' # which rules fire on a sample prowl rules validate ./team-rules ``` ## 模型与数据 基准测试语料库和阶段 3 的编码器已发布到 Hugging Face: - **模型:** [`Podric/prowl-secret-encoder`](https://huggingface.co/Podric/prowl-secret-encoder), 阶段 3 背后的多语言 transformer。 - **数据集:** [`Podric/prowl-secrets-corpus`](https://huggingface.co/datasets/Podric/prowl-secrets-corpus), 包含 50.3 万条带有完整溯源信息的标注记录(代码、工单、日志、散文)。 两者在评估期间均为私有状态。工具本身不需要它们;流水线是自包含的。 **在不使用扫描器的情况下使用模型** —— 将其作为 HTTP `/score` sidecar 运行(支持任何语言),将 `model_binary.json` L2 分类器嵌入到您自己的代码中,或者拉取 HF 编码器:参见 [`MODEL_INTEGRATION.md`](MODEL_INTEGRATION.md)。 ## 配置 位于仓库根目录的 `.prowl.yaml` 可以切换规则并调整白名单(兼容 gitleaks): ``` detectors: disable: [generic_high_entropy] # turn rules off allowlist: stopwords: [example, dummy] paths: ['_test\.go$', 'testdata/'] ``` 通过内联指令 `prowl:allow` 抑制源代码中的单行(同时也支持 `gitleaks:allow`)。 当您扫描不属于自己的代码时,在扫描树中自动发现的 `.prowl.yaml` 是由攻击者控制的,因此当某个配置禁用了检测器或添加了白名单规则时,会打印警告 —— 传入 `--config FILE` 以显式担保其安全性。实时验证(`--verify`)和 `prowl domain` 会拒绝连接到私有/回环地址(SSRF 防御);如果您要在内部或自托管的端点上运行验证器,请设置 `PROWL_ALLOW_PRIVATE_IPS=1`。 ## 构建 ``` cd tool make build # -> ./prowl make test # unit + integration make e2e # 50 end-to-end scenarios make ci # fmt + vet + build + race + e2e ``` 需要 Go 1.25+。无需外部服务。`tool/` 是扫描器(Go 编写)。检测规则和实时验证器位于一个单独的仓库中,[Lercas/prowl-templates](https://github.com/Lercas/prowl-templates) (通过 `prowl rules update` 安装);基准测试位于 [Lercas/prowlbench](https://github.com/Lercas/prowlbench)。 ## 许可证 Prowl 采用 **PolyForm Noncommercial License 1.0.0**:可免费用于非商业用途,不可用于商业产品。详见 [LICENSE](LICENSE)。
标签:AI应用开发, Apex, DevSecOps, Go, Ruby工具, StruQ, 上游代理, 日志审计, 机器学习, 机密扫描, 请求拦截