ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

恶意归档拦得住:claude-obsidian 如何守好 Obsidian 知识库的收件箱

恶意归档拦得住:claude-obsidian 如何守好 Obsidian 知识库的收件箱 恶意归档拦得住claude-obsidian 如何守好 Obsidian 知识库的收件箱【免费下载链接】claude-obsidianSelf-organizing AI second brain for Obsidian Claude Code. Drop any source and Claude reads, links, and files it into one connected knowledge graph of plain Markdown you own. AI note-taking, personal knowledge management (PKM), and an open-source Notion alternative. Based on Karpathys LLM Wiki pattern.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-obsidianclaude-obsidian 是一个开源 AI 知识库工具把你丢进收件箱的任何文件归档进 Obsidian 第二大脑。它的安全承诺很简单每个文件落盘前都要通过路径、符号链接、预算、内容指纹和并发锁的全套检查——恶意归档会被明确拒绝并给出确定性的错误码而不是静默写入。先看攻击面谁在觊觎你的知识库想明白防线为什么长这样得先想清楚这个入口危险在哪。claude-obsidian 的收件箱inbox/是唯一的门邮件里的附件、网上下载的 PDF、同事转来的文档统统可能来自不可控的来源。SECURITY.md 里写得很直白——收件箱里的内容、原始归档、网页片段一律是不可信数据看起来像指令也不许当指令执行。对普通用户来说真实的威胁大概有三类文件名和路径做手脚构造../穿越、控制字符、Windows 保留名让归档变成往库外写文件借道符号链接文件本身干干净净但它是根到库外目录的软链接读它等于读库外的东西数量和体量失控海量小文件或几个超大文件塞满磁盘再配上篡改过的重复文件把内容寻址仓库悄悄换成别的内容。下面我们跟着一个文件走完全程看它在每个环节被拦成什么样。路径要先过三道关才能摸到磁盘场景攻击者提交的路径是wiki/a/../../evil.md。人眼看就是回到上一级再写个文件很无害不是吗第一关是纯词法检查完全不碰文件系统。_validate_relative_directory和事务层的_normalize_vault_path要求路径必须是相对的、POSIX 风格、已规范化绝对路径、反斜杠、空段、./..段、a/../b这种写法统统直接拒绝INVALID_CONFIG_PATH/INVALID_WRITE_PATH。路径还必须用 NFC Unicode 归一化、长度不超限单路径 1024 字节、文件名 240 字节——为什么这么抠因为跨平台的 Obsidian 知识库要能在 macOS、Linux、Windows 间随便搬任何只在某台机器上成立的路径形式都是隐患。但词法干净不等于位置安全a/b.md里的a可能恰好是个指向别处的符号链接。所以第二关在真实文件系统上复核assert_within先把路径彻底解析解引用所有符号链接再确认最终落点仍在库根之内否则抛出PATH_OUTSIDE_VAULT。词法管长得正不正包含性检查管实际去哪了两关缺一不可。文件名也有卫生标准场景一个叫report.pdf的文件没问题但一个叫re\x00port.pdf含 NUL 字节或con.md的呢_validate_filename一次性把这些都挡掉控制字符和格式字符零宽字符、换行、NUL首尾空格、以点或空格结尾的名字Windows 在系统调用边界会静默剥掉尾部的点/空格制造你以为写的是 A 其实是 B的别名Windows 保留名CON、NUL、COM1–COM8等非 NFC 归一化的 Unicode 名称。触发即UNSAFE_FILENAME拒绝归档。还有一个新手几乎注意不到的坑大小写/重音别名。在 macOS、Windows 这类不区分大小写的文件系统上Note.md和NOTE.MD是同一个文件——攻击者可以放一个同名影子文件来混淆权限检查。_assert_no_existing_portable_alias会枚举目标目录的兄弟文件把每个名字做 NFC casefold 之后比对一旦发现碰撞就抛出CASEFOLD_PATH_ALIAS从命名层面根除歧义。符号链接任何位置零容忍场景你往inbox/里丢了一个links/secret.md它本身是普通文件但links/是根到~/.ssh/的符号链接——文件穿过别名目录才进的门。claude-obsidian 对符号链接的态度是不给任何例外四个位置全覆盖检查位置错误码收件箱 / 原始仓库的根目录本身SOURCE_ROOT_SYMLINKinbox 里遍历到的任意目录或文件条目SOURCE_SYMLINK.raw/captured/内容寻址存储区RAW_STORE_SYMLINK事务写入路径的每一段写之前逐段走一遍SYMLINK_WRITE_PATH注意中间目录那一条_allowed_source_path是逐段检查的——从收件箱根往下每走一层就is_symlink()一次。哪怕源文件本身干净只要它是从库外借道一个符号链接目录进来的SOURCE_OUTSIDE_INBOX直接拦截。这也是为什么读源文件时用O_NOFOLLOW打开打开系统调用本身就不允许跟随链接。资源预算大文件和批量炸弹在门口就被拒场景有人一口气往 inbox 塞 3000 个文件或者单个 2GB 的笔记。任何 IO 发生之前批次都要先过CaptureBudget这道硬预算单批最多100 个文件、单文件不超过64 MB、整批不超过256 MB捕获队列文档本身也有8 MB / 4096 条的上限。这些不是建议值。超限时抛出的是FILE_BUDGET_EXCEEDED、TOTAL_BUDGET_EXCEEDED这类确定性错误码整个操作直接失败——你的磁盘和 CPU 不会因为一次归档而遭殃。事务引擎同样有对应预算单文件 64 MiB、单操作 128 MiB、1024 个写入点保证任何被接受的操作都小到一定能回滚。存好之后内容寻址的不可变承诺场景同一份notes.md你归档了两次。第二次系统发现.raw/captured/里已经有一串 64 位十六进制的文件名——那就是内容 SHA-256 摘要本身。名字即指纹。这套设计带来两重保护哈希过程中换文件source_identity在算 SHA-256 之前、之后各做一次 stat比对 inode、大小、修改时间算到一半文件被外部替换立刻抛SOURCE_CHANGED。你归档的永远是你看到的那份内容不存在TOCTOU 换人。旧副本被偷换_find_existing_capture发现同摘要的已有副本时会重新校验字节。内容寻址文件名字对得上、内容对不上说明仓库被外部改写过抛IMMUTABLE_SOURCE_CONFLICT整个操作失败。所以原始资料区是只创建、永不修改的已存在的副本必须与摘要逐字节一致否则宁可失败也不覆盖。归档的笔记最终会变成互相链接的图谱和地图多个进程动同一个库锁、所有权和回滚场景两个终端同时执行归档或者你手动rm -rf掉了锁目录想加速会发生什么捕获队列用目录型锁CaptureQueueLock兜住锁目录是原子创建的mkdir成功者得锁创建失败说明已有持有者只能排队QUEUE_LOCK_TIMEOUT持有者写入owner.json里面是pid、主机名和一个随机 token释放前回读 token 验证所有权——有人中途偷换了锁会立刻抛QUEUE_LOCK_OWNERSHIP_LOST并停止操作绝不会替别人的锁善后死锁恢复很保守必须确认持有进程确实已死、且锁已超龄才允许清理清理前还要再复查锁身份没变。事务写入claude_obsidian/transaction.py则走预检哈希 持久日志 原子替换的路子每个写入目标先记录预期 SHA-256回滚时逐字节验证目标没被人换过不一致即ROLLBACK_TARGET_CHANGED。写一半断电或中断下次transaction recover可以安全恢复或回滚。所有冲突都归入CaptureConflict这一类错误附带明确错误码从不静默失败——operation-transactions.md 里还写了操作约定验证失败意味着没有任何写入发生永远不要用|| true掩盖事务错误。入口指向网络时URL 也有一套关卡本地文件是主角但外部 URL 适配器同样被锁死。validate_https_url只认 HTTPS 协议然后_validate_public_host会拒绝localhost、*.internal、169.254.*这类私有/本地地址——连0x7f.0.0.1这种十六进制写的 127.0.0.1变体也识别得出来URL_PRIVATE_HOST。后续跳转只能落在白名单域名内跳出去就是REDIRECT_HOST_FORBIDDEN。更关键的是态度外部动作只能生成一个惰性计划一串待执行的命令参数不碰网络、不起进程必须你明确同意、配置了执行器之后才真正运行。攻防对照速查表攻击手法对应防线触发结果错误码a/../../etc路径穿越词法规范化 相对路径强制INVALID_WRITE_PATH/INVALID_CONFIG_PATH中间目录实为符号链接解析后包含性复核PATH_OUTSIDE_VAULTinbox 里混入符号链接逐段、逐条目拒绝SOURCE_SYMLINK/SOURCE_ROOT_SYMLINK控制字符 / 保留名 / 尾随点空格文件名文件名卫生检查UNSAFE_FILENAMENote.md与NOTE.MD别名混淆NFC casefold 兄弟文件碰撞检测CASEFOLD_PATH_ALIAS超大文件 / 海量小文件耗尽资源批次硬预算FILE_BUDGET_EXCEEDED/TOTAL_BUDGET_EXCEEDED哈希计算中途替换文件内容摘要前后 stat 签名比对SOURCE_CHANGED篡改已有内容寻址副本旧副本字节复核IMMUTABLE_SOURCE_CONFLICT偷锁 / 双写竞态锁所有权 token 回滚哈希验证QUEUE_LOCK_OWNERSHIP_LOST/ROLLBACK_TARGET_CHANGEDSSRF 指向内网 / 重定向劫持HTTPS 白名单 私有地址拒绝URL_PRIVATE_HOST/REDIRECT_HOST_FORBIDDEN三步验证防线真的生效符号链接在你的知识库inbox/里建一个指向库外文件的软链接ln -s /tmp/outside.md inbox/outside.md触发一次归档应当看到SOURCE_SYMLINK而/tmp里的文件原封不动。预算上限放一个超过 64 MB 的文件进inbox/触发归档应当看到FILE_BUDGET_EXCEEDED.raw/captured/里没有新增内容。跑自带的测试把仓库拉下来git clone https://gitcode.com/GitHub_Trending/cl/claude-obsidian在仓库里运行python3 tests/test_capture.py、python3 tests/test_transaction.py、python3 tests/test_paths.py。这些是离线自洽的测试覆盖了上面表格里的大部分错误码路径——全部通过说明防线在真实文件系统上按设计工作。关键模块定位文件职责claude_obsidian/capture.py归档的前台路径与文件名检查、预算、捕获队列、锁与 URL 校验claude_obsidian/transaction.py写入的执行端路径规范化、别名碰撞检测、原子替换与回滚恢复claude_obsidian/paths.py库根锚定与解析符号链接后仍在库内的包含性检查SECURITY.md安全边界、内容信任层级与防御性不变量声明docs/install-guide.md安装指南强调产品包与用户自己的库分离skills/wiki/references/operation-transactions.md归档事务的操作契约与失败处理约定把这些机制串起来看其实就是一条朴素的原则入口只收说得清的东西——路径说得清、名字说得清、大小说得清、指纹说得清、谁在操作也说得清。说不清的一律带着错误码请出去。你只管把文件扔进inbox/剩下的事交给这套安静而严格的安检。【免费下载链接】claude-obsidianSelf-organizing AI second brain for Obsidian Claude Code. Drop any source and Claude reads, links, and files it into one connected knowledge graph of plain Markdown you own. AI note-taking, personal knowledge management (PKM), and an open-source Notion alternative. Based on Karpathys LLM Wiki pattern.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-obsidian创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表