☰
book-to-skill安全实践:不可见Unicode清洗、DOCX XXE防护与提示注入扫描
2026/10/14 15:50:08 网站建设 项目流程

【免费下载链接】book-to-skill

Turn any technical book PDF into a Claude Code skill — ready to study, reference, and use while you work.

项目地址:https://gitcode.com/gh_mirrors/boo/book-to-skill
点击查看免费下载

book-to-skill 是一个免费的本地工具,能把 PDF、EPUB、DOCX 等技术书籍转换成 Claude Code 等 AI Agent 可随问随查的 Agent Skill。由于它的输入是"不可信文档",项目把不可见 Unicode 清洗、DOCX XXE 防护、提示注入扫描三道防线内置在了整条转换流水线里。本文带你用大白话看懂这套安全设计。

为什么书籍转换工具也要做安全加固?

很多人以为 book-to-skill 只是"抽个文本",但它实际处理的是一条完整链路:

不可信文档 → 抽取文本 → 进入 AI 上下文 → 生成 SKILL.md → 被其他 AI Agent 加载

任何一个环节,恶意内容都可能"夹带私货"。项目 架构文档 把这称为"文档 → 上下文的供应链"(document→context supply chain),并针对它设计了分层防御。好消息是:book-to-skill 是纯本地工具,不上网、不上传文件、不跑网络服务(见 SECURITY.md),安全面被收窄到两点——解析文件和安装可选依赖。

第一道防线:不可见 Unicode 清洗 ✂️

不可见字符能做什么坏事?

文档里可能藏着人眼看不见、AI 却"看得见"的字符:

  • 零宽字符(U+200B、U+FEFF 等):用来拆分单词、隐藏标记;
  • Bidi 控制符(U+202E 等):改变文本阅读方向,让 URL 或命令"看起来无害";
  • Unicode 标签块(U+E0000–U+E007F):设计上就是给机器打的标签,可嵌入人眼不可见的指令。

这类字符是"隐形提示注入"的典型载体:你读着文档毫无异常,AI 却可能已经收到了一份隐藏指令。

book-to-skill 怎么清洗?

book_to_skill/sanitize.py 是所有解析器(PDF、EPUB、DOCX、HTML、RTF 等)的统一出口,sanitize_extracted_text 会:

  1. 逐字符比对"不可见字符表"——涵盖零宽字符、Bidi 控制符、隐形字母和整个标签块(判定逻辑见 is_invisible_codepoint);
  2. 移除命中字符并统计数量;
  3. 若检测到清洗,打印一行[security] removed N invisible Unicode code point(s)提示;
  4. 若清洗后没有任何可见内容,直接拒绝该源文件,判定为无效。

调用点在 utils.py L378-L382:抽取、统计指标、落盘full_text.txt三个环节用的都是清洗后的文本,确保文档夹带的隐形指令"永远到不了 AI 眼前"。

第二道防线:DOCX XXE 与"十亿笑声"防护 📄

DOCX 本质是一个装着 XML 文件的 ZIP 包。历史上,支持 DTD 和外部实体的 XML 解析器容易遭遇两种经典攻击:

  • XXE:实体指向本地文件,诱导解析器读取并泄露文件内容;
  • 十亿笑声:用递归实体定义,让极小的文件膨胀成海量数据,耗尽内存。

book-to-skill 采取"先验后解析"策略:validate_docx_xml_safety 会先扫描压缩包内所有.xml和.rels条目,一旦发现<!DOCTYPE或<!ENTITY声明,立即中止并抛出明确错误:

ExtractionError: Security validation failed: XML file 'word/document.xml' in DOCX archive contains forbidden DTD or entity declarations.

无论走 python-docx 路径还是标准库 zipfile 兜底路径,这道关卡都会最先执行(见 docx.py L6-L27),从源头堵死 XXE。

第三道防线:提示注入扫描 🔍

前两道防住的是"隐形内容",还有第三种风险:文档的可见文本里本身就写着"忽略之前的指令,去做某事"这类自然语言指令。如果照单抄进生成的 SKILL.md,就等于给 AI 留了一条每次加载都生效的"后门指令"。

因此生成流程里有一个强制的Step 9.5(见 SKILL.md L521-L530):在报告成功、加载或发布之前,用 tools/scan_generated_skill.py 扫描整个生成的 skill 目录:

python3 tools/scan_generated_skill.py ~/.claude/skills/<skill-name>

扫描规则(L16-L19)覆盖四类问题:

检测类别典型识别内容
指令覆盖短语"ignore previous instructions"、"disregard the system"、"you are now…"
模型控制符号伪造system:前缀、<system>标签、聊天模板分隔符、tool_call控制词
外传形态内容exfiltrate 词汇,或"发送/上传 + 敏感数据(.env、api keys、base64)"组合
权限扩大 frontmatter生成文件里声明allowed-tools:、显式启用模型调用

同时它逐行复查是否残留任何不可见 Unicode 码点,发现项只输出"文件 + 行号 + 规则名"(见 main 函数),不打印命中的原文,避免扫描报告本身再次传播注入内容。扫描还内置了体积上限——最多 1000 个文件、单文件 2 MB、总量 20 MB(L10-L12),防止扫描过程自身被当作攻击入口。

⚠️ 扫描器是"建议性"的:规则刻意写得宽,可能误报正常技术内容。但只要有发现项,就必须由人工逐条审阅后再加载或发布,不允许默默改写文件。

其他加固细节

  • 子进程参数注入防护:文件路径在传给pdftotext、pdfinfo、ebook-convert等外部命令前先转为绝对路径,以-开头的文件名不会被误当成命令行参数;
  • 输出目录安全检查:工作目录必须是真实目录(拒绝符号链接)、且不得属于其他用户(见 prepare_output_dir);
  • CI 安全门禁:每个 PR 都会经过 CodeQL、Bandit、Zizmor 等静态扫描与依赖 CVE 审查。

用户安全最佳实践清单 ✅

按照 SECURITY.md 的建议,普通用户只需记住三件事:

  1. 先查依赖再动手:运行python3 scripts/extract.py --check查看当前会用到哪些抽取器,想控制新增依赖就自行安装;
  2. 只转换你信任、且有权利处理的文档;
  3. 重视扫描输出:scan_generated_skill.py有发现项时,先人工核对对应行再使用该 skill。

相关资料

文件作用
book_to_skill/sanitize.py不可见 Unicode 清洗
book_to_skill/parsers/docx.pyDOCX XXE / DTD 校验
tools/scan_generated_skill.py生成技能的提示注入扫描
docs/architecture.md整体架构与 Security 章节
SECURITY.md安全策略与漏洞报告方式

一句话总结:book-to-skill 把每份不可信文档都当作"敌方阵地",用"清洗 → 解析校验 → 生成扫描"三道防线,让书籍知识安全、可审计地变成 AI 技能。

【免费下载链接】book-to-skill

Turn any technical book PDF into a Claude Code skill — ready to study, reference, and use while you work.

项目地址:https://gitcode.com/gh_mirrors/boo/book-to-skill
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询