全部技能 / 基础工具与工作流 / repomix-safe-mixer
基础工具与工作流 · daymade/claude-code-skills

repomix-safe-mixer

Safely package codebases with repomix by automatically detecting and removing hardcoded credentials before packing. Use when packaging code for distribution, creating reference packages, or when the user mentions security concerns about sharing code with repomix.

风险提醒:蓝色 · 知晓即可AI 侦查报告
作者 daymadeGitHub daymade/claude-code-skills ↗Stars 1392许可 MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)commit d5c4678cb5
agent 宿主通常会约束 skill 执行权限;风险提醒为 AI 侦查观点,不构成质量或安全保证。第三方 skill 仅作拆解与展示,安装使用风险自负,版权归原作者。

1实现原理 · 为什么它能做到

编排方式是「子进程 + JSON 契约」:safe_pack.py 不导入扫描器,而是用 subprocess 调同目录的 scan_secrets.py 并加 --json,再解析其 stdout 决定是否打包。

repomix-safe-mixer/scripts/safe_pack.py
cmd = [sys.executable, str(scan_script), str(directory), '--json']
注:这里在做什么:两个脚本解耦成『扫描器(纯函数式 CLI,有 JSON 与退出码契约)+ 编排器』,让扫描器可独立用于 pre-commit/清理验证,同时让编排器不依赖扫描器内部实现。

检测能力来自一张 13 项的正则字典(SECRET_PATTERNS),全部是行内正则匹配,无 AST、无熵值分析、无机器学习。

repomix-safe-mixer/scripts/scan_secrets.py
'aws_access_key': r'(?i)AKIA[0-9A-Z]{16}', 'aws_secret_key': r'(?i)(?:aws_secret|aws.{0,20}secret).{0,20}[=:]\s*["\']?([0-9a-zA-Z/+=]{40})["\']?', 'supabase_url': r'https://[a-z]{20}\.supabase\.co', 'supabase_anon_key': r'eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*', 'stripe_key': r'(?:sk|pk)_(live|test)_[0-9a-zA-Z]{24,}',
注:这里在做什么:正则而非语义分析 → 规则完全透明可审计、零依赖、可离线跑;代价是只认『长得像』的凭证(详见 verification 第 4、6 条的漏报面)。

扫描范围由「扩展名白名单 + .env 文件名特例」双重界定,且代码注释明确解释了为什么必须给 dotenv 开特例(Path('.env').suffix == '')。

repomix-safe-mixer/scripts/scan_secrets.py
# Full filenames that must be scanned regardless of Path.suffix. Dotenv # files break suffix matching: Path('.env').suffix == '' and # Path('.env.local').suffix == '.local', so scanning by extension alone # silently skips the most common places secrets end up. SCANNABLE_FILENAMES = { '.env',
注:这里在做什么:把『密钥最常出现的地方』(.env 系列)硬编码进扫描面,避免只按后缀扫描时把最该查的文件漏掉——这是该脚本里唯一带有反事实推理痕迹的设计。

跳过目录是硬编码集合(node_modules/.git/.venv/dist/build 等 15 个),不做 gitignore 解析。

repomix-safe-mixer/scripts/scan_secrets.py
SKIP_DIRS = { 'node_modules', '.git', '.venv', 'venv', '__pycache__', 'dist', 'build',
注:这里在做什么:控制扫描成本与噪音;代价是被 ignore 目录里若真藏密钥不会报,且 --exclude 只能加不能减这些默认跳过项。

假阳性抑制有两条硬规则:占位符词表命中即跳过,且对整行做 substring 判断(只要该行任意位置出现 'example'/'test-' 等词,本行所有命中都被丢弃)。

repomix-safe-mixer/scripts/scan_secrets.py
placeholders = [ 'your-', 'example', 'placeholder', 'xxx', 'yyy', 'zzz', 'test-', 'demo-', 'sample-', '<YOUR_', '${', 'TODO' ]
注:这里在做什么:降低占位符误报;但实现是 line_lower 级判断而非 match 级——一行里既有真密钥又出现 'example' 就会被整行放过,抑制范围大于 SKILL.md 描述的『跳过 test/example/sample 文件』。

注释行一律跳过(行首 // / # / /* / *)。

repomix-safe-mixer/scripts/scan_secrets.py
if re.search(r'^\s*(?://|#|/\*|\*)', line):
注:这里在做什么:假定注释里的是示例;副作用是被注释掉的真实凭证(常见于调试残留)不在报告内。

默认 fail-closed:命中即拒绝打包并 exit 1,只有显式 --force 才会继续;--force 路径仍打印警告。

repomix-safe-mixer/scripts/safe_pack.py
print("❌ Cannot pack: Secrets detected!")
注:这里在做什么:把『安全扫描』从建议变成闸门——SKILL.md 对此的承诺是『3. Blocks packaging if secrets found』,与代码一致(唯一的例外是 --force 与下方的空 stdout 失败路径)。

打包动作是调用外部 CLI repomix:把目标目录作为 cwd,透传 --config/--output,产物由 repomix 写盘。

repomix-safe-mixer/scripts/safe_pack.py
result = subprocess.run(cmd, cwd=directory, capture_output=True, text=True)
注:这里在做什么:本 skill 自身不实现打包,只做『先扫后包』的顺序编排;repomix 以列表 argv 形式调用(无 shell=True),目录路径不会变成命令注入。

报告会回显命中的密钥片段与命中行上下文到 stdout(--json 下 match 截断 50 字符、context 截断 100 字符;人类可读报告打印 match/context 前 80 字符),但脚本本身不写任何文件。

repomix-safe-mixer/scripts/scan_secrets.py
print(f" Match: {finding.matched_text[:80]}") print(f" Context: {finding.line_content[:80]}")
注:这里在做什么:让用户能定位到具体文件与行号;副作用是密钥明文片段进入终端输出——在 agent 会话中这些输出会进入模型上下文与对话记录,属于『不外发但也不静默』的中间地带。

退出码即接口:有命中返回 1、干净返回 0,SKILL.md 明确把它当作 pre-commit 钩子用(阻断提交)。

repomix-safe-mixer/scripts/scan_secrets.py
sys.exit(1 if findings else 0)
注:这里在做什么:让扫描器可嵌进 CI/git hook;但注意 safe_pack.py 调它时并不检查返回值,只看 stdout 能否解析成 JSON(见 verification 第 3 条的 fail-open 风险)。

2核心能力

01打包前密钥扫描:12 类规则的凭证检测(AWS 访问键/密钥、Supabase URL 与 anon key/JWT、Stripe、Cloudflare token、R2 账号 ID、Turnstile、OAuth secret、私钥块、通用 API key)
02命中即阻断打包(fail-closed,退出码 1),并给出修复步骤清单
03受控越权:--force 跳过阻断但仍警告(文档明示 NOT RECOMMENDED)
04独立的扫描器用途:清理后复验、pre-commit 钩子、存量代码审计(--json 供程序化消费)
05按类型分组的发现报告(同类只展示前 3 条,其余折叠计数)
06repomix 打包编排:透传 --config / --output,在目标目录内执行
07假阳性抑制:占位符词表、注释行、示例/测试文件(--exclude 追加)
08凭证修复范式与泄露后处置(env 变量替换 → .env.example → 复验 → 打包;泄露后 rotate/revoke/audit/monitor)

3外部依赖

类型依赖
clirepomix(第三方打包 CLI,需用户自行预装)
clipython3(sys.executable 拉起同目录扫描器;仅标准库 os/re/sys/json/subprocess/pathlib)
packagerepomix(npm 生态包,本 skill 只调用命令,不负责安装)

4风险提醒 风险提醒:蓝色 · 知晓即可

风险提醒:蓝色 · 知晓即可
  • 扫描失败的 fail-open:只承诺『发现即阻断』,不覆盖『扫描没跑成』 — run_secret_scan 不读 result.returncode,stdout 为空即视为无命中,随后照常打包。若 python 解释器异常或扫描器崩溃(stderr 有输出、stdout 为空),用户会看到『✅ Packaging complete!』而实际未经扫描;建议在 CI 中改为同时断言扫描器退出码。
  • 检测覆盖与文档不符,存在稳定的漏报面 — 无 Gemini AIza 规则、无 R2 access key 规则,裸 sk- 形式不一定命中;且 *.pem/*.key/id_rsa/*.toml/*.ini 等不在扫描扩展名白名单内,private_key 规则几乎无用武之地。SKILL.md 的检测类型清单会被读者高估。
  • 假阳性抑制按整行生效,真密钥可能被同行噪音放过 — should_skip_match 对 line_lower 做 substring 判断,行内出现 'example'/'test-'/'xxx'/'TODO' 之一即整行免检;注释行同样整行跳过。真实代码中『示例值 + 真实值』同行的配置或调试残留会被漏掉。
  • 报告回显密钥片段与原始文本,进入 agent 上下文/会话记录 — scan_secrets.print_report 打印 matched_text[:80] 与 line_content[:80],--json 保留 match[:50]/context[:100]。对 agent 会话而言这既是敏感片段留痕,也是把不可信仓库的文件内容带进模型上下文的注入通道(可构造 'Match:' 行干扰阅读)。
  • --force 文档措辞误导 — SKILL.md 标题『Force pack (dangerous, skip scan)』暗示免扫描,实际仍完整扫描并报告,只是跳过阻断——使用者若据此认为『--force 更快』会造成误解(功能上其实更慢且危险)。
风险提醒:蓝色,知晓即可。行为面:两个标准库本地脚本,零网络调用(无 requests/urllib/socket/http/curl/wget,SKILL.md 中的 https:// 全部是占位符或参考外链)、零凭证外发;读取目标目录内文件(含 .env 系列)是扫描功能的必要前提,匹配结果只打印不落盘;仅调用本地 CLI(repomix 为需预装的第三方 npm 命令,以 argv 列表方式调用,无 shell 注入面)。需留意:①命中片段与命中行原文会被回显到 stdout,在 agent 会话中即进入模型上下文与对话记录,对不可信仓库存在报告文本注入与密钥片段留痕两个隐患;②编排器不检查扫描子进程退出码,stdout 为空时会 fail-open 直接打包,与 SKILL.md『Blocks packaging if secrets found』的强承诺存在实现缺口,建议在 CI 中改为同时校验退出码。

5第二遍独立确认

  • [ok] 外部依赖调用点反查(repomix / python3) — 全目录 grep subprocess 仅 3 处命中:safe_pack.py 的 import、L24 subprocess.run(调 scan_secrets.py,cmd 来自 cmd = [sys.executable, str(scan_script), …])、L74 subprocess.run(cmd, cwd=directory)(cmd 起点为 cmd = ['repomix'])。两个依赖条目均有真实调用点,无第三处。
  • [ok] 网络外发反例查找 — grep requests|urllib|urlopen|socket|http|curl|wget 在两个脚本内零命中;SKILL.md 与 common_secrets.md 中的 https:// 全部是占位符(https://your-project-ref.supabase.co)、示例域名(.r2.cloudflarestorage.com 出现在正则 lookahead 文本中)或文档外链。无 DNS/HTTP 客户端、无遥测、无任何外发路径。
  • [discrepancy] 扫描器返回码未被校验 → fail-open 反例 — run_secret_scan 只做 result = subprocess.run(...);随后 findings = json.loads(result.stdout) if result.stdout.strip() else [],从不检查 result.returncode。若扫描器因解释器缺失/脚本损坏/进程被杀而 stdout 为空,findings 被判为空列表,main 直接进入 '📦 Packing … with repomix' 分支——即『扫描失败』被当成『无密钥』。这与 SKILL.md『3. Blocks packaging if secrets found』的强承诺存在实现缺口:只承诺了『发现密钥时阻断』,未覆盖『扫描本身失败』。
  • [discrepancy] SKILL.md 检测类型清单 vs SECRET_PATTERNS 实际键 — SKILL.md 列出 11 类(AWS Access Keys、R2 Account IDs/Access Keys、Supabase URL/Anon Keys、Stripe、OpenAI sk-、Google Gemini AIza、Generic API Keys、JWT、OAuth Client Secrets、Private Keys、Turnstile)。代码 SECRET_PATTERNS 实为 12 个键,但其中:无 R2 Access Keys 专用规则;无 Google Gemini(AIza…)规则(全目录 grep 'AIza' 零命中);OpenAI sk- 仅在同时出现 api_key/apikey 字样时可被 generic_api_key 捕获,stripe_key 只认 sk_live/sk_test 形式,因此裸的 sk-proj-… 赋值不一定会命中。文档检测类型清单宽于代码能力。
  • [discrepancy] 假阳性抑制范围 vs 文档描述 — SKILL.md『Common False Positives』写的是跳过占位符、『Files matching .*test.*, .*example.*, .*sample.*』的文件与注释行。should_skip_match 实际对整行做 substring 包含判断(placeholder in line_lower),且注释判定用 ^\s*(?://|#|/\*|\*)——即抑制粒度是『行』而非『match』或『文件』:真密钥与 'example' 同行即被放过,被注释掉的真实凭证亦不上报。代码抑制面大于文档描述,属漏报向的偏差。
  • [discrepancy] 扫描面缺口:不在白名单的高风险文件类型 — SCANNABLE_EXTENSIONS 只含 .ts/.tsx/.js/.jsx/.py/.md/.json/.yaml/.yml/.sh/.bash/.zsh/.sql/.go/.java/.rb/.php/.cs,SCANNABLE_FILENAMES 只补 7 个 dotenv 名。因此 *.pem、*.key、id_rsa、*.ppk、*.p12、*.crt、.envrc、*.toml/*.ini/*.conf/*.properties/*.xml 都不被扫描——private_key 规则(-----BEGIN … PRIVATE KEY-----)写好了却基本没有机会命中这些最常见的私钥载体。SKILL.md 未提示该覆盖边界(仅笼统说 may not catch all credential types)。
  • [discrepancy] --force 语义与文档措辞一致性 — SKILL.md 标题写『**Force pack (dangerous, skip scan)**』,暗示跳过扫描;safe_pack.py 中 force = '--force' in sys.argv 之后仍照常执行 run_secret_scan 与 print_findings_report,只是跳过阻断并打印『WARNING: --force flag set, packing anyway despite secrets found!』。实际语义是『扫描照做、仅放行』,措辞『skip scan』不准确。
  • [ok] 证据是否指向被扫文件内容/是否落盘 — 两脚本无 open(...,'w')、无 tempfile、无日志写入;匹配结果只经 print/ json.dumps 到 stdout(scan_secrets 的 to_dict 将 match 截断 50、context 截断 100;人类可读报告打印前 80 字符)。『不落盘、不外发』成立;但『不进日志』不成立——终端输出在 agent 会话中会被留存为上下文。

6结论

  • 默认 fail-closed 的强制顺序,把安全校验做成闸门而非建议
  • 规则集透明、零依赖、可离线审计并直接嵌入 CI
  • 能力边界自述诚实,不冒充完整安全审计
  • 配套参考文档把『发现问题』接到『修好问题』
  • 适合:适合:把本地代码库打包成 repomix 包对外分享前的最后一道自检;需要在 CI/pre-commit 里加一个零依赖、退出码即结论的密钥扫描;需要一份可读、可改的正则规则表来按自身栈扩展检测项(如加 AIza 或 .pem 规则)。典型用法是 CI 里跑 `scan_secrets.py . --json` 卡提交,分享前跑 `safe_pack.py <dir>` 做『扫描通过才打包』。
    不适合:不适合:把安全性托付给它的场景——它是模式匹配而非完整 secret scanning,漏报面明确,不能替代 gitleaks/trufflehog/CI 平台密钥扫描与 git 历史清理(SKILL.md 自己也这么声明);不适合扫描私钥文件为主的仓库(*.pem/id_rsa 不在扫描面);不适合不可信仓库直接在 agent 会话里跑(报告会把仓库文本回显进上下文);也不适合期望『自动移除凭证』的场景——官方描述里的『removing hardcoded credentials』实际是人工按报告修改,脚本只做检测与阻断。
    安装 agent 直装可复制
    ① 本站镜像 更新 2026-09-15
    方式 A · 人下载镜像包下载 repomix-safe-mixer.tar.gz
    sha256: 7847e6113e529f6b…
    方式 B · JSON 格式安装指南,复制给 agent
    安装指南
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② 上游 GitHub · 原始来源
    能访问 GitHub?直接去上游安装(实时版,可能已更新)GitHub 原始 ↗
    本页镜像锁定 commit d5c4678cb5;上游为实时仓库。
    来源信息 GitHub 原始
    作者 / 仓库daymade / daymade/claude-code-skills
    Stars1392
    最近推送2026-09-09
    本 skill commitd5c4678cb5
    许可MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)
    本站信息
    收录日期2026-09-06
    分类基础工具与工作流
    侦查报告AI 侦查 · 2 遍 · 2026-09-06
    本站镜像与 GitHub 原始是不同来源:本站锁定 commit 快照经 /r2 分发;GitHub 为实时上游,内容可能已更新。
    同分类邻近