惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
Lohrmann on Cybersecurity
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
S
Schneier on Security
I
Intezer
Latest news
Latest news
N
News and Events Feed by Topic
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
量子位
博客园 - 【当耐特】
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
NISL@THU
NISL@THU
The Cloudflare Blog
李成银的技术随笔
T
ThreatConnect
L
LINUX DO - 最新话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
有赞技术团队
有赞技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Jina AI
Jina AI
T
Tor Project blog
The Hacker News
The Hacker News
人人都是产品经理
人人都是产品经理
小众软件
小众软件
S
Security Archives - TechRepublic
美团技术团队
博客园 - Franky
Security Latest
Security Latest
J
Java Code Geeks
P
Proofpoint News Feed
V
V2EX
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Help Net Security
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
Hugging Face - Blog
Hugging Face - Blog
N
Netflix TechBlog - Medium
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
SecWiki News
SecWiki News
腾讯CDC
爱范儿
爱范儿
D
Docker

掘金

juejin.cn juejin.cn juejin.cn Transformer 原论文怎么训出来的:8 张 P100、12 小时、warmup 4000 步 Transformer 中的前馈网络:那个看似平平无奇的两层 MLP,其实是「记忆」所在 AI Coding开始进入第四个时代,我还没上车呢! 【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (1)---基础 09aa-偏置是什么? Vibe Coding 全栈实战:章鱼哥解题 01|搭好产品底座与登录链路 CSS 已死?DOM 性能黑洞!Pretext 排版革命让你在文本间跳舞,没有 DOM 也能纵享丝滑~ 我让 AI 加了一个开关,结果代码走了原本不该走的分支 Manim物理模拟:别自己写欧拉了! 《道德经》简单解说版-第 2 章:天下皆知美之为美 juejin.cn juejin.cn Android Input Spy Window Claude Code CLI 命令大全:60 个原生命令一次讲清 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn 关于一个新手小白靠claude帮助下的全栈留言板项目开发 juejin.cn juejin.cn juejin.cn 从本地开发到生产部署:用 Docker Compose 跑通 NestJS、MySQL 与 Milvus AI应用开发七:可以替代 RAG 的技术 juejin.cn 小书匠:一款本地优先、去中心化的全能笔记软件 juejin.cn juejin.cn juejin.cn Shadow实战接入与生产落地:从零搭建到稳定运行 Shadow Transform:编译期的魔法——字节码替换实战 juejin.cn juejin.cn Hermes Agent:一个真正“会成长”的开源 AI Agent,正在改变 AI 自动化玩法 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn CryptoJS:数据安全的JavaScript加密利器 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn ArkClaw AI 盯盘管家 —— 从手动口令到自动推送,4 套预置定时任务模版一键启用 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn “杀!杀!杀!”、“我最讨厌事后道歉”——骂“杀哥”之前,谁还没当过情绪崩溃的人 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn Crawlee StagehandCrawler:自然语言点 Load More 的工程化爬虫 juejin.cn juejin.cn juejin.cn juejin.cn 人人都在鼓吹的OPC,我想给你泼盆冷水 juejin.cn juejin.cn juejin.cn Redis内存用爆了,原来我们都忽略了这个配置 juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn juejin.cn Android 专家岗 Kotlin 面试题:能答出这些,说明你对语言设计有自己的理解 juejin.cn juejin.cn 业务系统集成 OpenClaw 多 Agent 方案:从架构到落地的完整指南
Hermes 升级后,我的 Telegram 附件突然发不出来了
孟健AI编程 · 2026-05-25 · via 掘金

大家好,我是孟健。

今天这个坑很小:文件生成了,Telegram 收不到。

GitHub 提交截图:Fix unsafe gateway media path delivery

01 小坑:文件生成了,手机收不到

场景很具体。

Agent 生成了一张配图,路径回来了,MEDIA:/tmp/article-cover.png。消息发出去了,Telegram 显示发送成功,打开手机——只有文字,附件不见了。

第一反应是 bot 挂了。重启,没用。然后去查 Telegram bot API 的状态,正常。再想会不会是文件大小超限,检查了一遍,几百 KB,格式 PNG,都没问题。换了一次代理,还是没有。又想是不是发送时机问题,写了个脚本反复重试,依然空手而归。

就这样折腾了半小时,每一步看起来都"成功了",但手机那边始终没有附件。

最后去翻 gateway 日志,才找到真正的原因。日志里有一条很短的记录:文件路径未通过安全校验,上传跳过。消息本身发出去了,但文件根本没走到上传这一步。

回头翻提交记录,看到 2026-05-22 有一条 Fix unsafe gateway media path delivery,改动涉及 gateway/platforms/base.pytools/send_message_tool.pycron/scheduler.py 等文件。不是 bug,是主动升级。

这是 Hermes 安全模型的一次有意为之的收紧。升级之前,Agent 说"发这个文件",gateway 就发。升级之后,多了一道闸门,Agent 说的路径得过了校验才能上传。

看起来是附件消失,实际上是安全模型在替你挡了一枪。

02 为什么要拦:MEDIA 路径本质是不可信输入

理解这道闸门,先想清楚一件事:AI 生成的文件路径,其实就是一段文本。

Agent 回给 gateway 的内容是 MEDIA:/tmp/article-cover.png,这个字符串是 LLM 生成的。LLM 在生成这个字符串的时候,没有去碰文件系统,没有打开过这个文件,没有验证它存在不存在,更没有检查它该不该发出去。它只是根据上下文生成了一串看起来合理的路径文本。

这就是问题所在。LLM 能生成 MEDIA:/tmp/article-cover.png,也完全可以生成某个敏感配置文件、凭据文件,或者服务器上任何一个存在的本地路径。不需要恶意攻击,只需要上下文稍微偏一点,或者有人通过 prompt injection 给 Agent 塞了一段特定指令。

如果 gateway 的逻辑是"看到 MEDIA 标记就上传",这个链路就等于把服务器文件系统的读权限,通过 Telegram bot,间接开放给了任何能影响 Agent 输出的人。攻击面很明显,不是假设风险。

Hermes 的安全文档里强调 defense-in-depth,从命令审批、用户授权,到凭据处理、Web 安全、SSRF 防护、prompt injection 拦截,是多层设计,不依赖单一防线。文件上传这里,是在"Agent 输出"和"实际交付"之间加了一环独立校验。

这个设计原则很清楚:Agent 的输出跟用户输入一样,都是不可信文本,必须在边界上做验证。

不信任用户输入,是 Web 开发的基本常识。把同样的不信任延伸到 Agent 输出,是 AI 系统进入生产后必须面对的现实。

Hermes 源码截图:validate_media_delivery_path 校验逻辑

03 Hermes 现在怎么判断一个文件能不能发

核心逻辑在 gateway/platforms/base.pyvalidate_media_delivery_path(path) 函数里,五步校验,顺序不能乱,每一步都有对应的防护目标。

第一步,绝对路径检查。 传进来的路径必须是绝对路径,相对路径直接返回 None,不做后续处理。相对路径依赖调用时的工作目录,不同进程、不同时机,解析结果可能完全不同,不具备可预期性。

第二步,文件存在检查。 路径合法不等于文件在。路径指向的文件必须在磁盘上真实存在,否则拒绝。这一步过滤掉了大量"路径是 LLM 编出来的"情况,Agent 有时候会幻觉出一个听起来合理但根本不存在的路径。

第三步,普通文件检查。 必须是普通文件,目录、socket、字符设备、块设备一概不行。防的是通过传入目录路径来绕过、或者上传设备文件触发意外行为。

第四步,symlink resolve。 如果路径是软链接,先解析到真实路径,然后再做后续校验。这步非常关键,防的是一种经典绕过手法:把软链接本身放在允许目录下,但链接指向目录外的敏感文件。不 resolve 直接检查软链接路径,就会放行。

第五步,安全根目录检查。 解析后的真实路径,必须落在 Hermes 自管理的 media cache 目录下,或者在 HERMES_MEDIA_ALLOW_DIRS 环境变量显式声明的目录下,缺一不可。五步里任何一步不过,函数返回 None,上传终止,消息文本正常发出,附件静默跳过。

我做过验证:/tmp/article-test-media.txt 传进去返回 None,直接被拦;media_outbox 下的文件,通过全部校验,可以正常上传。

实测截图:outbox 放行,/tmp 拦截

/tmp 是最常见的"生成文件随手往这放"的场景,但它不在安全根目录里,也确实不该被默认允许。/tmp 是共享临时目录,任何进程都能往里写,把它加进白名单,等于把 gateway 的上传权限开给了整台机器上所有能写 /tmp 的进程。

五步校验的逻辑是:你要发的文件,必须是你可控范围内的文件。

04 我最后怎么修

拿到原因之后,面前有两个选项。

一是把整个 workspace、/tmp 或者用户主目录加进 HERMES_MEDIA_ALLOW_DIRS。一行环境变量的事,能立刻解决问题,但等于把刚加的闸门拆了,白升级。安全升级不是摆设,绕过它不是"快速修复",是主动降级。

一是建一个统一的附件出口,在不破坏安全边界的前提下,给 Agent 一个合法的、有明确边界的操作空间。

我选了第二个。

测试截图:安全根目录、目录外文件、软链接逃逸都被覆盖

方案核心:~/.hermes/media_outbox 作为唯一对外附件目录。

具体分四步走:

建 outbox 目录。 ~/.hermes/media_outbox/ 是所有对外附件的唯一出口,含义明确。里面只放要发出去的文件,不往里随意堆其他东西。目录本身的存在,就是"这里的文件都是准备发出去的"这个语义的体现。

写预处理脚本。 ~/.hermes/scripts/media_outbox_prepare.py 负责把原始文件从生成位置复制进 outbox。复制前做三件事:扩展名白名单校验,只允许 png、jpg、pdf、mp4 等常见格式,其他一律拒绝;文件大小上限校验,防止发出去一个几 GB 的文件把 bot 撑死;文件名脱敏,去掉内部绝对路径信息,生成的目标文件名不带任何内部目录结构。脚本的输出是绝对路径形式的 MEDIA:/.../.hermes/media_outbox/...,Agent 直接拿这个路径发消息,不需要再做任何额外处理。

注入环境变量。 通过 systemd drop-in 文件,给所有 gateway service 注入 HERMES_MEDIA_ALLOW_DIRS=<绝对路径>/.hermes/media_outbox。所有平台的 gateway 自动生效,不需要逐一配置,也不会漏掉某个 service 忘记改。

定时清理。 加了一个 cron 脚本,保留 14 天内的文件,自动清理过期附件。outbox 有专门用途,不能让它随着时间堆成新的垃圾桶,清理是 outbox 设计的一部分,不是事后补丁。

这套方案的整体逻辑:安全根目录的边界不动,但在边界内,给 Agent 划出一个受控的合法操作空间。文件想出去,必须先经过 outbox 这道门,门里有格式校验、大小校验、文件名校验。什么文件能出去,一目了然,审计起来也方便。

安全边界必须是硬的,靠 prompt 说"你不要发敏感文件",是靠自觉,自觉不可靠。

05 这个小坑给 Agent 产品的启发

做 Hermes 到现在,这是第一次正经遇到"Agent 能生成,但系统不允许它交付"的情况。乍一看像 bug,实际上是系统行为正确——它拦住了一个本该被拦住的操作。

过去做 Agent 产品,大部分精力放在能力上:它能不能理解需求,能不能写对代码,能不能生成好内容,能不能在多个工具之间正确协作。这些很重要,是 Agent 有没有用的前提。但进入生产工作流之后,真正难的是另一侧——能做什么和不该做什么的边界,必须是系统层面的约束,不能靠 prompt 来撑。

靠 prompt 控制边界,是让 Agent 自己管自己。这个思路有一个根本性的弱点:Agent 越智能,它"智能地绕开限制"的能力也越强,而且往往不是主动的,是场景和上下文把它推过去的。你 prompt 里写了"不要发敏感文件",但 Agent 在执行某个工具链的中间节点,根本意识不到当前文件是不是"敏感的",因为它没有访问文件内容,只有路径字符串。

系统层面的约束才是稳的。发文件,有 outbox,只有 outbox 里的文件能出去;发消息,有审批,只有审批过的内容能对外;删数据,有确认,人没点确认就不执行。这些约束让 Agent 可控地做事,让系统知道它在做什么,做了什么,做了多少。可观察性和可控性,是 Agent 在生产里长期跑的基础。

对所有在做 Agent 产品、把 Agent 接进实际工作流的人,我的建议是:凡是涉及文件、凭据、发布、支付、删除、外发这几类操作,都要有显式出口 + 安全闸门。显式出口让你知道什么东西会出去,安全闸门让你确认它该不该出去。出口和闸门缺任何一个,都是把管控权悄悄让渡给了 Agent。

这篇讲的是 Telegram 附件,但同样的逻辑适用于所有"Agent 产出要触碰真实世界"的地方。邮件要发出去,文章要推送,代码要部署,金额要扣除——每个环节都是一道门,门上有没有锁,锁是不是系统级别的,决定了整个工作流安不安全。

Agent 越像员工,就越不能让它随手拿办公室里的任何文件。


👋 我是孟健,前腾讯 T11 / 前字节技术 Leader,现在全职做 AI 编程。

🔥 更多 AI 编程实战:

  • GitHub:@mengjian-github
  • 专栏:AI编程实战

觉得有用?点赞+收藏 就是最大支持 🙏