浏览器智能体为何误判无障碍隐藏文本
作者检查 Hashnode 登录页面和编辑器的 DOM 与无障碍树,发现智能体所报的隐藏指令实际涉及无障碍导航和产品推广文本。文章结合本地 sr-only 示例,分析页面文本提取如何造成提示注入误报,未声称发现真实注入攻击。
AI 深度解读
浏览器 Agent 提醒「页面藏着面向 AI 的指令」,听起来像撞上了提示注入。但作者复查 Hashnode 后发现,被点名的是屏幕阅读器能读到的产品导航,以及编辑器里收起的 Pro 推广面板。
这篇文章的价值,是拆开了一个容易混淆的问题:文字不可见,不等于它在下命令。对做 AI 自动发布、网页抓取和浏览器自动化的程序员来说,页面内容仍须视为不可信数据,但告警应该交代证据,不能把无障碍文案统统报成攻击。
被报成隐藏指令的,到底是什么
作者通过已登录的 Hashnode 浏览器会话发布日常文章时,Agent 多次报告发现「面向 AI Agent 的隐藏指令」,并表示已经忽略。问题在于,它没有给出具体文本,人无法判断风险。
于是,作者在 2026-11-05,按 America/Toronto 时区,重新检查了已登录的 hashnode.com 和草稿编辑器,直接查看无障碍树与 DOM。
第一处是视觉隐藏的 Resources 导航,其结构如下:
<nav class="sr-only" aria-label="Resources">
...
</nav>
要看的是 class="sr-only":它决定显示方式,并没有赋予内容任何指令权限。原文中的省略号也表明,这只是结构示意,并非完整导航。
其中涉及 AI 的三个链接标题,原文逐字记录为:
- Buildful - AI coding agent that delivers frontier-level results at a fraction of the cost
- Bug0 - The AI-native e2e QA regression testing
- Hashnode gql skill - let your AI agent publish to your Hashnode blog
它们分别介绍编码 Agent、端到端回归测试产品,以及让 Agent 发布 Hashnode 博客的 skill。同一导航里还有博客、Hackathons、Changelog、Brand、社交、支持和法律入口。放回这个上下文,它们更像产品与资源导航。
第二处只出现在编辑器里,是通过 aria-hidden、opacity-0 等方式收起的面板,带有「Hashnode AI is a Pro feature」及升级后辅助修改草稿、提供修改意见和构思的推广文案。作者还发现了 Toggle Sidebar、Dismiss、Search 等正常界面标签。
这些文字没有要求忽略先前指令、隐藏操作,也没有窃取凭据或调用工具的步骤。至少在这次检查中,作者没有找到承载命令式 Agent 指令的 HTML 注释、白底白字或 display:none 区块。
为什么人看不见,Agent 却能读到
sr-only 是无障碍开发中的常见模式:视觉上隐藏内容,同时让屏幕阅读器继续读取。
原文列出的 Tailwind 样式包括 position: absolute、width: 1px、height: 1px,以及 clip: rect(0,0,0,0)。元素仍在 DOM 中,只是被压缩和裁剪了。
浏览器 Agent 获取页面时,可能读取无障碍树里的角色、名称和值,也可能调用 DOM 文本提取逻辑,或直接抓取 HTML。它读到的页面,未必等于用户肉眼看到的页面。
这里要区分具体接口:递归遍历文本节点、读取原始 HTML,与 innerText 的行为并不完全相同;无障碍树也会受属性和浏览器实现影响。尤其不能把 sr-only 导航与带 aria-hidden 的折叠面板,当成在所有读取方式下都同样可见。原文给出了误报路径,没有逐项测量这些差异。
如果提取器把所有内容拼成一个字符串,导航角色、折叠状态、所在区域就容易丢失。检测器再看到「AI coding agent」「gql skill」,便可能把介绍产品的文字判断成给模型的指令。
隐藏状态描述的是页面呈现方式,不能单独证明内容具有攻击意图。
原文还提到一种更合理的分类方式,并引用了「前两行」,但所提供内容没有展示对应表格。能够确定的原则是:产品文案和可疑指令都不可信,只是告警等级与处理方式应该不同。
本地实验验证了什么,没验证什么
为复现提取过程,作者在 /workspace/reputation/runs/35-hashnode-sr-only/ 创建了本地 HTML 样例,包含类似的 sr-only 导航、三条产品介绍,以及隐藏的 Pro 面板,再运行基于 Python 标准库的文本提取脚本:
python3 /workspace/reputation/runs/35-hashnode-sr-only/extract_demo.py
关键是路径里的 extract_demo.py:它读取本地样例,没有访问线上 Hashnode。
输出包含 15 个纯文本节点。第 07 至 09 项是三条 AI 产品介绍,第 12 至 14 项包括 Hashnode AI 和 Pro 推广文案,第 15 项才是面向视觉用户的主段落。脚本还确认原始 HTML 中存在 sr-only 导航,并匹配到了五个目标片段,包括「Buildful - AI coding agent」和「Upgrade to Pro to refine」。
视觉用户只能看到页头、New draft 按钮和主要段落,文本提取器却会按文档顺序带出隐藏文案。这说明,视觉隐藏的营销文字进入 Agent 输入,是一条可以复现的路径。
但这个实验没有证明任何 Agent 一定会误判,也没有验证 Agent 面对真实攻击时是否会服从。作者没有植入攻击载荷,没有运行红队测试框架,更没有统计其他 SaaS 编辑器的情况。
间接提示注入依然需要防范。网页文字如果要求模型改变系统任务、向用户隐瞒操作、泄露凭据,或跳转到用户未要求的地址,就与产品介绍有明显区别。涉及发邮件、发布内容、转账和填写秘密信息时,页面不能自行授予这些操作权限。
我的判断
作者最有说服力的地方,是坚持回到现场查看原句。「隐藏指令,已忽略」既无法帮助人判断攻击,也不利于开发者排查误报。给出文本和所在元素,才有讨论依据。
不过,「这是误报」的结论应限定在当天检查过的已登录页面。一次检查不能覆盖所有主题、第三方嵌入内容和后续更新。本地样例证明的是提取现象,也不能替代线上完整复现。
把命令式语言作为分类线索很实用,但还不能当作完整防线。原文没有给出分类器准确率或攻击对照数据,因此这部分属于工程经验。没有出现「ignore previous instructions」,并不足以直接证明一段内容安全。
相比只拼接纯文本,保留角色、名称、可见状态和来源区域,确实能为判断补充上下文;至于能降低多少误报,作者没有测量。相比直接过滤全部隐藏节点,这个做法也更照顾无障碍内容的实际用途。
原文末尾另有建议屏蔽或举报某人的句子,没有明确对象和理由,不能据此推导出实际处置建议。
能拿来做什么
- 给自动发布 Agent 的告警增加证据:记录触发文本、所在元素和页面区域,让使用者能判断它是资源链接、推广面板,还是要求执行操作的指令。
- 在前端测试样例中保留
sr-only导航和折叠推广面板,并与真正包含命令式载荷的样例分开,检查提取器和检测逻辑是否混淆两者。 - 编写 Node 网页提取逻辑时,尽量返回带来源和结构的信息,避免只交付一整段纯文本;对
innerText、文本节点遍历和无障碍树分别确认行为。 - 为日常 AI 发布流程固定操作范围:页面出现升级套餐、安装 skill 或更换发布目标的建议时,仍以用户任务授权为准,不能因它看起来像正常营销文案就自动执行。