在截图中查找凭据,将其提取到密钥管理器,并不可逆转地将它们从图像中隐去——这样秘密就不会在你的笔记、截图和 ~/Desktop 中腐烂。
本地。离线。静默。默认无网络、无遥测。
screenscrub 连接了两个现有的工具类别:GUI 隐去工具(Xnapper、Shhshot、macshot)手动模糊 PII,但无法区分秘密与地址,也无法捕捉它们隐藏的内容;秘密扫描器(gitleaks、TruffleHog)能发现真实的凭据,但仅限于文本,从未出现在 PNG 中。screenscrub 将 gitleaks 级别的检测——外加红队包和熵分析——引入像素图,以无头方式执行:它将每个秘密捕获到你的管理器,不可逆地隐去图像,并重新 OCR 结果以证明秘密已消失。
一张安全网,而非保证——screenscrub 从不声称图像“保证干净”;OCR 和检测都可能遗漏,因此请始终亲自检查结果。在依赖它之前请阅读此内容。
screenscrub scan ~/Screenshots # 模拟运行:检测+报告,不写入
screenscrub clean ~/Screenshots --out ~/clean \ # 提取、隐去、验证、隔离
--sink file://./secrets.age --yes
screenscrub verify ~/clean # 证明文件夹干净(否则退出码≠0)
screenscrub clean --keep-originals ./tmp
Cleaning 7 image(s) in ./tmp (7 worker(s))…
[1/7] tmp/ssh.jpg — 6 region(s) → tmp/ssh.redacted.jpg ✓ verified
[2/7] tmp/key.jpg — 13 region(s) → tmp/key.redacted.jpg ✓ verified
[3/7] tmp/test2.jpg — 12 region(s) → tmp/test2.redacted.jpg ✓ verified
[4/7] tmp/test5.jpg — 13 region(s) → tmp/test5.redacted.jpg ✓ verified
[5/7] tmp/test3.jpg — error: verification failed: 4 secret region(s) still detectable in tmp/test3.redacted.jpg; original preserved
[6/7] tmp/test4.jpg — error: verification failed: 9 secret region(s) still detectable in tmp/test4.redacted.jpg; original preserved
[7/7] tmp/test6.jpg — error: verification failed: 7 secret region(s) still detectable in tmp/test6.redacted.jpg; original preserved
7/7 file(s) flagged, 382 region(s) total, 3 file(s) errored/unverified.
By kind:
high-entropy 343
keyword-secret 15
db-connection-uri 10
github-pat 6
unix-crypt-hash 6
aws-access-key 1
stripe-key 1
Needs manual attention (3):
tmp/test3.jpg — error: verification failed: 4 secret region(s) still detectable in tmp/test3.redacted.jpg; original preserved
tmp/test4.jpg — error: verification failed: 9 secret region(s) still detectable in tmp/test4.redacted.jpg; original preserved
tmp/test6.jpg — error: verification failed: 7 secret region(s) still detectable in tmp/test6.redacted.jpg; original preserved
| 之前 — 秘密值可见 | 之后 clean — 不可逆隐去 |
![]() |
![]() |
同一张截图在 clean 前后:每个秘密值被解码为像素、框定并重新编码到新图像中(不可逆)——标签和结构保持可读。
需要 tesseract OCR 二进制文件在 PATH 上:
brew install tesseractwinget install UB-Mannheim.TesseractOCR(或 UB Mannheim 安装程序)apt-get install tesseract-ocr然后构建:
go build -o screenscrub ./cmd/screenscrub
可交叉编译到 macOS(arm64/amd64)和 Windows(amd64)——它通过外部调用 tesseract,而不是使用 cgo。仅已在 macOS 上测试。
scan <dir|file> — 模拟运行检测并报告;不写入任何内容。
screenscrub scan ~/Screenshots --ignore 'node_modules/**' --ignore '*.thumb.png'
screenscrub scan shot.png --json # 机器可读报告
screenscrub scan ~/Screenshots --preview ~/review # 目测 clean 会隐去什么
--preview <dir> 写入每个标记图像的非破坏性副本,其中每个检测到的区域被描边(未填充),以便你在提交之前确认 clean 会隐去哪些内容。⚠️ 这些副本仍包含秘密——目录以 0700 权限创建,不得共享。
报告以汇总结束:按类型细分以及显式的**“需要手动关注”**列表——出错、验证失败或对应该是截图的内容未产生任何 OCR 文本的文件(无声的 OCR 遗漏与干净图像读取相同,因此被提出而不是信任)。
scan --fail-on-findings 在检测到任何内容时退出码非零——用于预提交/CI 门控。
clean <dir|file> — 提取、隐去、隔离SCREENSCRUB_PASSPHRASE=… screenscrub clean ~/Screenshots \
--out ~/Screenshots/clean \
--sink file://./secrets.age \
--yes
对于每个有发现的图像,clean:
<name>.redacted.png 写入 --out(或源文件旁),<out>/quarantine/。秘密被传递给你通过 --sink 指定的 sink:age 文件(默认)、1Password(op://)、KeePassXC(keepassxc://)、macOS Keychain(keychain://)或 HashiCorp Vault(vault://)——或基于硬件的 age 接收者(YubiKey、Touch ID)。参见秘密接收端。
标志:
| 标志 | 含义 |
|---|---|
--out <dir> | 隐去副本的输出目录(默认:源文件旁) |
--sink <uri> | file://./secrets.age · op://Vault · keepassxc://./v.kdbx · keychain://service · vault://KV |
--recipient <age1…> | 加密到 age 接收者(可重复):X25519、YubiKey 或 Touch ID |
--recipients-file <f> | 包含 age 接收者的文件,每行一个 |
--passphrase | 文件接收端/隔离的密码短语(优先使用环境变量或 --config) |
--watch | 持续运行;处理新到达的截图(fsnotify) |
--purge | 粉碎原始文件而不是隔离(请参阅下面的说明) |
--keep-originals | 仅写入隐去副本;保持原始文件在原位(无隔离、无密码短语、无 --yes)——与 --purge 互斥 |
--yes | 确认破坏性原始处理(必需) |
--config <file> | JSON 配置;允许将密码短语排除在 argv 之外 |
--no-verify | 跳过隐去输出后的重新 OCR 验证(不推荐) |
-i, --interactive | 打开每个标记图像并在处理前确认隐去/跳过 |
--llm | 使用 Claude 剔除良性过度标记;将候选字符串发送到 Anthropic API |
--llm-api-key | --llm 的 Anthropic API 密钥(或 ANTHROPIC_API_KEY) |
--jobs N | 并行处理 N 个图像(默认:CPU 数量) |
--manifest <file> | 写入 JSON 映射:原始→隐去→区域 |
--ocr-raw / --ocr-upscale N | 禁用暗色终端预处理 / 在 OCR 前放大 |
--exclude-kind <kind> | 抑制某个类型的发现(可重复),例如 high-entropy——离线精度调节旋钮 |
--min-confidence <0..1> | 丢弃低于此置信度的发现——离线精度调节旋钮 |
--json | 以 JSON 输出报告 |
--ignore <glob> | 忽略 glob,可重复;** 匹配任意深度 |
--lang | tesseract 语言(默认 eng) |
--exclude-kind 和 --min-confidence 是用于噪声语料库的本地(无网络)精度调节旋钮——是 --llm 的离线对应物。它们以召回率为代价换取更安静的报告,因此请有意识地使用。两者也适用于 scan/verify,并可在 --config(exclude_kinds、min_confidence)中设置。
密码短语解析顺序:--passphrase,然后是配置文件,最后是 SCREENSCRUB_PASSPHRASE。避免在命令行上使用 --passphrase —— argv 对其他进程可见。
verify <dir|file> — 证明文件夹干净重新 OCR 每个图像,重新运行检测,如果发现任何秘密区域仍然存在,则退出码非零——在将截图交付给客户之前,用作可交付物/CI 门控。(它证明 OCR 无法读取秘密,而非人类永远无法读取。)
screenscrub verify ~/deliverable/screenshots
echo $? # 0 = 干净,非零 = 秘密仍然可检测
clean 在每个隐去副本上自动运行相同的检查,如果隐去副本失败,则不会隔离或粉碎原始文件;--no-verify 跳过它(不推荐)。
open <store> — 恢复秘密或隔离的原始文件取回你的数据:open 将 age 接收端(已存储的秘密记录)或隔离的原始文件解密到 --out,绝不输出到 stdout。参见解密存储。
--llm — 使用 LLM 剔除良性过度标记gitleaks 级别的规则应用于 OCR 文本(带有 OCR 噪声)不可避免地导致过度标记:偏向召回率的检测器会标记出操作员希望保留的良性高熵字符串——主机名、GUID、Git SHA、NTLM 哈希(这些哈希本身就是妥协的证据)。--llm 将每个候选字符串传递给 Claude(Opus 4.8),保留真正的秘密并丢弃良性标识符;LLM 确认的区域会被填充为红色。
ANTHROPIC_API_KEY=… screenscrub clean ~/Screenshots --out ~/clean --llm --yes
这有意打破了本地和静默的默认行为:它将候选字符串(检测到的秘密)发送到 Anthropic API,因此仅限 opt-in,会打印警告,并且需要 API 密钥。它退出时安全关闭:任何 API/网络错误都会保留所有发现(隐去所有内容),而不是冒险丢弃真正的秘密。每个标记图像进行一次 API 调用(最多并发 4 个,与 --jobs 无关)——请注意大型目录上的速率限制和成本。
--watchscreenscrub clean ~/Screenshots --watch --sink file://./secrets.age --yes
处理所有已存在的文件,然后监听新的/修改的图像,并在它们出现时逐一隐去。*.redacted.png 输出会被忽略以避免循环。
在 OCR 令牌之上,screenscrub 结合了:
AKIA…、GitHub ghp_…、GitLab、Slack、Stripe、OpenAI、GCP API 密钥、JWT 和 PEM 头。(复制而非导入,以保持小巧和完全离线。)postgres://u:p@…)、HTTP Basic/Bearer 认证头、NetNTLMv2 和 NTLM(pwdump)哈希、/etc/shadow crypt 哈希、PuTTY 和 OpenSSH 私钥、SendGrid/npm 令牌。password、token=、secret、api_key、……)——即使不匹配任何模式且熵较低,也会标记相邻的值。BEGIN/END 标记,并慷慨地隐去整个包围区域,而不是信任逐词匹配。每个命中都映射回组成它的令牌的像素框(两种行重构方法——间隔和紧凑——恢复 OCR 在空白处分割的秘密),并在填充前对框进行扩展。
接收端是一种方法:Store(Secret) error。提供的适配器: