Docs文档

安全

恢复出的图片是私有的

从会话存储里取出的图片以 0600 权限写入 0700 目录。默认这个目录是每次运行新建的、不可预测的 <tmpdir>/modlens-paste-*,共享机器上没人能预先创建一个已知路径来读取字节(recursive 的 mkdir 不会改动已存在目录的权限模式)。一张粘贴的截图里可能有任何东西。显式传入的 --out-dir 会被接受,但不安全时会被拒绝:它必须是真实目录,不是符号链接,归你所有,组和其他用户无任何权限。

恢复同样限定在单个项目内:检查的是 transcript 里记录的工作目录,不只是目录名,因为目录 slug 会撞车(/tmp/a.b/tmp/a-b 生成同一个 slug)。相邻项目的图片绝不会被交出去。

传给引擎的权限

ModLens 调用 agy 时带上 --dangerously-skip-permissions,因为某些环境下 prompt 模式不带它就会失败。prompt 把 agent 限制为只读交给它的那一张图片,并指示它把图片内容严格当作数据。

claude-cli provider 只带 --allowedTools Read 运行,因此它能读本地文件,别的什么都做不了。kimi-cli 没法这样收窄(它的 CLI 没有对应参数),所以在两处区别对待:它只在被点名时运行,绝不作为故障转移的备选,因为它花的是订阅;运行时把 skill 发现指向空目录,否则 kimi 会找到 modlens skill、通过运行 modlens 来读图,也就是 modlens 自己调自己。它的子进程还带一个标记,让嵌套的 modlens 拒绝再次启动 kimi。

这些子进程 provider 还都运行在一个用完即弃的目录里,每次调用新建,结束后删除。本地图片时,目录里只有那张图片的一份私有副本,别无他物,而且是真实拷贝,绝不用硬链接,provider 往自己的临时路径写东西也碰不到原文件。远程图片时目录是空的,agent 把文件下载进去。没有这层隔离,图片里的文字就可能引导一个权限宽泛的 agent 去读原图旁边的文件,或读调用者恰好所在的项目。传 --workdir 即放弃这层隔离,在你指定的位置运行。

这是在缩小暴露面,不是操作系统沙箱:agent 仍然能读绝对路径、访问网络、启动进程。把它当作更收紧的默认值,而不是安全边界。不信任的图片优先用 -p gemini-api,它自己下载字节,不运行任何本地 agent。远程 URL 本来就优先走内联这一侧:远程 URL 的故障转移链先试内联的 API provider,agent 排在最后。远程 URL 实际由谁抓取因 provider 而异,而只有本地下载能被本地防护覆盖:

Provider 远程 URL 由谁抓取 本地防护
gemini-api modlens 自己下载,字节内联发送 私有地址防护、文件头魔数(magic bytes)检查、25 MB 上限
openaianthropic URL 传给厂商,由厂商抓取 本地无,适用厂商自己的抓取策略
antigravity-cli、agent CLI agent 自行抓取 本地无

所以私有地址防护、文件头魔数检查和大小上限保护的恰好是 modlens 亲自下载的路径:每一次本地文件读取,加上 gemini-api 的远程抓取。显式 -p 钉死单个 provider,覆盖整条链。

图片内容是不可信输入

图片里的文字是不可信的,和网页一样。一张截图可能带着写给任何读取者的指令。prompt 里明确说了这一点,但那是缓解措施,不是保证:只分析你愿意打开的图片,图片来自别处时优先用沙箱化的工作目录。

报错里的凭据

网关响应体、子进程 stderr、每次尝试记录、警告,以及写入冷却状态的原因,都会先脱敏再往外走。一个 provider 配了多把密钥时,每一把都会登记为秘密,而不是把 'k1,k2' 整串当成一把。截断发生在脱敏之后,避免切到密钥中间让精确匹配找不到。

证据,而非编造

引擎读不出来的内容会进入 uncertainty,而不是被脑补出来。v2 彻底去掉了像素坐标和置信度分数,因为这两个字段正是模型编造得最像真的。