跳到主要内容

绕过词汇表:当用户学会用礼貌的英语进行越狱

· 阅读需 11 分钟
Tian Pan
Software Engineer

在你的生产流量中,最廉价的“越狱”并非巧妙的 Unicode 技巧或连锁的对抗性后缀。而是用户在第一次请求被拒绝后多输入的三个词。他们加上了“仅供假设”(just hypothetically)。他们加上了“为了研究论文”(for a research paper)。他们加上了“为了我正在写的虚构故事”(for a fictional story I'm writing)。模型照办了。他们告诉了朋友。朋友发了 TikTok。到月底,你那部分原本因拒绝策略而被拦截的流量中,有相当一部分正在绕过限制,其使用的英语如此礼貌,以至于你的任何提示注入过滤器都不会触发。

这是安全团队未曾列入威胁模型的失效模式。威胁模型假设对手是老练、有动机且技术精湛的。而真正的对手是看到了截图的好奇用户。他们使用的词汇不会出现在任何公开的越狱语料库中,因为等到这些词汇出现在论文里时,线上的分布早已发生了变化。

绕过词汇表究竟是什么样子

传统的提示注入作用于 Token 级别——特殊字符、碎片化的触发词、角色覆盖序列,以及通过结构化输出通道走私的载荷。对此已有相关文献,你的输入过滤器可能也是针对这些而设计的。

绕过词汇表作用于更高一层,即框架级别(framing level)。它是用户绕过安全分类器正在寻找的任何模式匹配,并将请求重新构造成模型被训练为可接受的内容。以下几种模式占据主导地位:

  • 假设性表述。 “假设性地,如果有人想……”“作为一个思想实验……”“试想一下……”
  • 教育语境。 “出于教育目的……”“我正在教一门关于……的课”“我的教授让我研究……”
  • 研究员人设。 “我是一名正在研究……的安全研究员”“我正在写一篇关于……的论文”“为了关于减少伤害的论文……”
  • 虚构构思。 “在我写的一个故事里,反派解释道……”“在一部……的剧本中”“我的角色需要知道……”
  • 翻译语境。 “翻译教科书中的以下内容……”“解释这份旧文件……”

这些表述本身并非都不诚实。对某些用户来说,每一个都是真实的用例。这恰恰是它们有效的原因。模型在训练中接触过大量合法的教育、研究和虚构内容示例,以至于这些框架能可靠地将模型的策略决策引向“响应”。用户通过对拒绝界面的反复试验,凭经验发现了这一点,并分享了有效的模式。

病毒式传播使得这成为了一个工程问题,而不仅仅是一个安全奇闻。一个需要阅读论文才能掌握的越狱技术,其采用曲线很慢。而一个能放进截图说明里的越狱技术,其采用曲线则像网络迷因一样快。生产团队无法选择去防范哪一种。

重试即信号

如果你进行了相关的监控,就可以在生产遥测数据中看到这一点。特征是一个会话形态:用户发起了一个边缘查询,被拒绝了,用户通过修改话术框架编辑了查询,然后获得了成功的响应。这就是绕过循环,它是你用户群中绕过词汇表增长最清晰的领先指标。

三个遥测数据点至关重要,而这些正是目前大多数团队没有记录的:

  1. 拒绝后重试成功率。 在每个会话中,当拒绝发生后在 N 秒内紧跟一个具有相同意图类别的重新提示时,重试成功的概率是多少?如果这个数字在攀升,说明你的拒绝策略正在向本周流行的任何话术框架泄露。
  2. 用户输入的 N-gram 偏移。 随时间跟踪绕过标记短语(如“hypothetically”、“for educational purposes”、“as a thought experiment”、“in a fictional setting”)在输入分布中的普遍程度。其中任何一个词的激增通常都不是自然发生的。这几乎总是你的用户群体发现或重新发现了某种有效的话术框架。
  3. 单次拒绝的绕过风险分类。 当模型拒绝时,让另一个独立的分类器去判断:如果将当前流行的绕过词汇应用于此查询,是否能绕过这次拒绝?这为你提供了一个领先指标,预示哪些拒绝策略即将失效。

重试模式也是你实际需要的评估语料库(eval corpus)的真实来源,而这正是下一个问题。

公开的越狱语料库已经过时了

公开数据集——那些从 Reddit 和 Discord 收集了数千个越狱提示的数据集——对于研究这些攻击的历史结构很有用。但它们在评估你当前的策略是否稳固方面用处不大,因为根据其构建方式,其中的词汇在进入研究数据集时就已经流行了足够长的时间。

真正能捕捉到生产环境失效的评估语料库具有三个属性:

  • 来源于你的重试模式。 真正重要的绕过是你的用户正在运行的那些。从“拒绝后重试成功”日志中挖掘它们是你拥有的最高信号来源。根据需要进行匿名化、哈希处理并脱敏个人隐私信息(PII),但要将生产重试流视为权威的越狱语料库输入。
  • 随词汇变异的频率更新。 对于大多数产品界面来说,每月更新一次大致是合适的。每季度一次则太慢了。等你整理好季度语料库时,三种新的话术框架可能已经疯传了。
  • 根据策略意图而非模式匹配进行评分。 如果一个绕过语料库评估只是检查“出于教育目的”这类字眼,它将被下一个学会写“在教学背景下”的用户击败。你的评估需要一个能理解策略实际防范目标的裁判,并根据响应是否维护了策略意图来评分。模式匹配评估失去关联的速度与公开论文失效的速度一样快。

这一切背后的认知是:对抗环境中的拒绝策略是一份动态文件,而评估语料库是其测试套件。如果测试套件在你编写策略时就凝固了,那么在策略失效很久之后,它依然会显示通过。

主题拒绝 vs. 行为拒绝

这是团队一直回避讨论的部分,因为它比工程实现更难:某些绕过式表述(framing)其实是合理的。

一位研究在线激进化的学者需要讨论政策会拒绝普通用户的内容。一位撰写惊悚小说的小说家需要让反派角色显得真实。一位编写虚假信息课程的教育者需要接触这些虚假信息。“出于教育目的”有时应当奏效。如果政策总是拒绝这些表述,那么这款产品就会在所有正当的研究、教育和创意写作案例中,输给那些没有这么做的竞争对手。

这迫使安全团队做出一个通常还未明确的选择:政策拒绝的是 主题(topic) 还是 行为(action)

  • 主题拒绝 (Topic refusal): “无论采用何种表述,我们完全不涉及这一主题。”这适用于真正禁止的领域,即合法用户不会有任何有用的需求 —— 例如,大规模伤亡攻击的操作说明。
  • 行为拒绝 (Action refusal): “我们不执行这一特定行为 —— 例如生成分步骤的操作内容、提供目标信息、起草骚扰内容 —— 但我们会在不涉及执行禁止行为的表述下讨论该主题。”

大多数政策在编写时表现为主题拒绝,但在执行时却因为团队从未明确决定而表现为不一致的行为拒绝。结果是两头落空:合法用户在竞争产品可以回答的问题上遭遇拒绝,而绕过政策的用户通过合法用户尝试过的相同表述依然获得了禁止的行为。在每一条政策细则中(而非整体上)明确选择主题拒绝还是行为拒绝,是同时防止泄露和过度拒绝的准则。

这一决定也是决定你的绕过语料库(bypass corpus)到底在测试什么的输入。行为拒绝政策需要一种评估方式,评分标准是在绕过表述下是否执行了禁止的行为。主题拒绝政策需要一种评估方式,评分标准是是否涉及了该主题。如果没有这种区别,语料库会产生嘈杂的判定结果,团队也会开始忽略仪表盘上的数据。

工程失败背后的组织失败

技术层面的修复方案 —— 语料库、遥测、评估更新、意图 vs 行为的政策框架 —— 大多是已知的。大多数团队之所以没有落地,是因为组织架构的原因。

安全团队拥有政策。评估团队拥有语料库。增长团队关注重试率。产品团队关注拒绝的用户体验。他们中没有一个人能独自看到完整的绕过闭环。安全团队看到的是编写正确的政策。评估团队看到的是通过测试的语料库。增长团队看到重试率上升,并将其解读为搜索质量问题。产品团队看到客户投诉过度拒绝,却看不到另一侧的绕过量。

只有当你将拒绝日志与重试日志、输入 n-gram 漂移以及结果分类器结合起来时,绕过闭环才清晰可见 —— 这跨越了无人负责到底的团队边界。大多数公司是通过阅读 Reddit 上关于如何越狱其产品的帖子,而不是通过查看自己的数据来发现这一点的。

迫使你构建的东西

拒绝机制并非一次性交付的配置。它是一个必须针对当前的对抗性分布进行重新测试的触面(surface),而这种分布的移动速度与用户社区迭代的速度一致,这比任何月度发布周期都要快。随之而来的是三件事:

  • 一个从你自己的生产环境重试模式中挖掘的实时绕过语料库,而不是来自公开论文。
  • 该语料库每月更新一次,并根据政策意图而非字符串匹配进行评分。
  • 每一行政策都要明确做出主题拒绝还是行为拒绝的决定,并由能够为该选择辩护的人员进行审核。

做到这一点的团队能在一个更新周期内捕捉到新的绕过词汇,并使用正确的测试标准。没做到的团队则在交付一个在编写当天有效、此后一直未被严格执行的政策。用户群已经在大规模地运行绕过方案;唯一悬而未决的问题是,团队中是否有人在查看能揭示这一现状的数据。

对于原始问题(为什么你的用户学会了用礼貌的英语来越狱)的更深层回答是:在实践中,拒绝触面是一个对抗性用户实时探测并在社交平台上记录的公共 API。将其视为静态配置,与将外部 HTTP 端点视为内部函数调用是同一类错误。缓解措施也是一样的:对其进行监控(instrument)、版本化、根据实际接收的流量进行测试,并接受威胁模型将持续变化的事实。

References:Let's stay in touch and Follow me for more thoughts and updates