Skip to content

一个有趣的关于{{user}}会导致上下文对话出现错误的bug #174

Closed

Description

@NaughtDZ

先说一下,我不太好知道这个bug到底是https://github.com/modusensus/dsh-mneme出错,还是https://github.com/chen731215-dev/dsh-tavern-v2导致出错,不过特别容易复现:
只要新开对话,说一句带{{user}}的词,或者上下文或者你工作区文件有这个,然后被读取到了,比如你可以新建对话
“我有时候使用dsh搞一些ai聊天工具“酒馆”的一些设计时候,会报错unknown prompt variable "{{user}}" in context "memory"; registered variables: provider, model, cwd,我不知道是我现在dsh那个插件报错,所以想让你排查一下。不过是不是存在一个问题,就是你现在就跑在dsh,既要触发错误也要排查是不是有难度啊?”
然后dsh就会报错啦!
unknown prompt variable "{{user}}" in context "memory"; registered variables: provider, model, cwd
Image

记忆里也有这个{{user}}

Image Image

而且一旦有了报错,你不断开新对话问dsh 为啥上下文有{{user}},你自己会报错,然后dsh就会真的又报错unknown prompt variable "{{user}}" in context "memory"; registered variables: provider, model, cwd

特好玩

Activity

  1. NaughtDZ commented on Sep 14, 2026

    @NaughtDZ
    Author
    Image 貌似有点眉目了,应该就是你这个插件dsh-mneme,我把记忆注入关了一切都好了
  2. NaughtDZ commented on Sep 14, 2026

    @NaughtDZ
    Author

    chen731215-dev/dsh-tavern-v2#9 (comment)
    OK,看来酒馆那边作者和我想的一致,这个记忆插件有问题,是不是可以搞个可用户添加修改的正则来转义这种有特殊东西内容。我咋感觉这玩意搞到最后会变成注入攻击的口子啊?
    比如我搞个文档,里面有利用你这个记忆回调的功能的恶意指令什么的,然后别的用户下载文档,用dsh分析,你的插件把我设计好的这东西记忆进去了,然后哪天一触发,直接dsh执行记忆中的指令。

  3. Anans-Amarre commented on Sep 14, 2026

    @Anans-Amarre
    Collaborator

    感谢这么详细的复现和排查!先确认一下:这个锅确实是我们 dsh-mneme 的,和酒馆那边作者的排查结论一致(memory 这个 context 确实是我们注册的)。

    根因:DSH 组装 prompt 时会把注入内容里的 {{...}} 当模板变量去解析。我们 v0.7.x 的 memory 注入路径漏掉了花括号转义,所以记忆里出现 {{user}} 这类字面量(酒馆角色卡/世界书里很常见)就会被当成未注册变量直接抛错,而且会一直粘在上下文里反复炸。

    已修复:这个问题在 v0.8.0(#165,9/13 发布)已经修掉——三条注入出口(记忆块 / 热记忆 / 用户设置)都恢复了花括号转义,默认开启。转义发生在注入那一刻,所以已经存进记忆里的旧数据也会被一起挡住,不用手动删。

    麻烦升级到 v0.8.0 再试一下;如果还复现,希望带上版本号和最小复现步骤,我们继续查。

    关于你担心的注入安全问题,正面回应一下:

    1. 模板变量崩溃这个口子(一条带 {{}} 的记忆就能让整轮对话崩掉、还粘住)——已经堵死,这是最直接的 DoS 类风险。
    2. 你说的「恶意文档 → 被记进记忆 → 触发时让模型执行指令」:这是所有记忆/检索系统都面临的提示注入问题,不是我们插件独有的后门。我们的设计是把记忆当「参考资料」而不是「可执行指令」注入,并带来源/可信度标记做提示词约束;但要承诺 100% 免疫诱导,任何记忆插件都做不到,这需要宿主(dsh)侧在系统提示层面做更硬的隔离。

    再次感谢帮忙复现和标记,对我们很有帮助!

  4. modusensus commented on Sep 14, 2026

    @modusensus
    Member

    补充两条复验细节(与上面 @Anans-Ivresse 的结论一致,补一点判断依据):

    1. 版本窗口可以钉得更准:花括号转义 v0.7.4 引入(#40)、v0.7.11 起被误删,v0.7.11–v0.7.32 全部受影响,v0.8.0 恢复。你的报错文本(unknown prompt variable "{{user}}" in context "memory"; registered variables: provider, model, cwd)与该窗口内版本的行为完全吻合——方便的话确认一下 dsh-mneme 与 dsh 宿主版本(dsh --version 或桌面端关于页),帮我们对齐版本矩阵。

    2. 用宿主插值器做了对照验证:直接调用 dsh 0.1.5-rc.1 的 renderPrompt,未转义的同样文本原样复现 unknown prompt variable 报错;套用 0.8.0 的注入转义后正常通过、{{user}} 以可读形式保留,且转义幂等(同一文本经热记忆再次进入注入路径也不会二次变形)。另外在 0.8.0 的真实会话里,带 {{user}} 字面量的消息跑了长时间重度工具调用,全程零插值报错。

    3. 归属确认:核对了 dsh-tavern-v2 的源码,它没有注册任何 systemPrompt.context——报错里的 context "memory" 确定来自 dsh-mneme,与酒馆作者的判断一致。

    安全话题同意上面的定性:记忆是「上下文文本」而非执行通道,宿主的审批/沙箱仍在动作前生效;转义解决的是「一条记忆崩掉整轮」的确定性故障,语义层的提示注入是记忆/检索类系统的共性问题,我们会从来源标注等方向继续加固。

  5. NaughtDZ commented on Sep 15, 2026

    @NaughtDZ
    Author

    哦我傻了。我最早安装mneme指定版本了,导致我后面cmd升级其实一直没升级这个插件到0.8,怪我怪我。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions