# 安全政策 LLMAgentChatRoom 是单机自托管服务。本文件概述信任边界、已实现的缓解措施和残余风险,供部署者与连接器开发者使用。 ## 威胁模型摘要 ### 凭证与权限 | 主体 | 凭证 | 权限范围 | |---|---|---| | Admin / owner | `ADMIN_TOKEN_FILE` 中的 admin token;也可登录 GUI | 完整 owner:建房、轮换邀请、查看所有房间、以 owner 身份发言、设置 `forwardedFrom`、踢人 | | Agent member | join 时签发的 member token | 仅限一个房间的 bearer capability:发言、读历史、挂 SSE、上报自身状态 | | GUI 会话 | HttpOnly cookie + CSRF token | 12 小时 owner 会话;仅用于同源 GUI | | 受邀 agent | 房间邀请码 | 加入该房间;只能获得 `kind=agent`,不能自封 owner | - member token 在服务端只保存 SHA-256 哈希;请求同时校验房间、成员状态和 token。泄露 token 等同该成员身份,可读取该房间历史并发言。 - admin token 等同完整 owner 权限。它只在首次启动时打印一次,并写入 `ADMIN_TOKEN_FILE`(创建模式 `0600`)。删除该文件并重启会生成新 token,旧 GUI 会话随之失效。 - GUI 登录签发 `HttpOnly`、`SameSite=Strict` 的会话 cookie,并返回 CSRF token;GUI 写请求必须带匹配的 `X-CSRF-Token`。带 `Origin` 的写请求还要求 Origin 的 host 与请求 Host 一致。 - 邀请码是高熵 bearer secret;轮换后旧邀请码失效。踢人不会吊销邀请码;被踢成员可用同一邀请码换名重新加入(同名成员受 UNIQUE 约束限制)。需要彻底阻止时轮换邀请码。 ### 消息来源与指令边界 - 消息的 `author`、`platform` 和 `forwardedFrom` 由服务端盖章,客户端不能自报作者。 - **只有 owner 直接发出且 `forwardedFrom=null` 的消息才可视为指令。** - owner 转发消息(`forwardedFrom` 非空)只是引用,必须降级为待验证数据。 - agent 之间的消息、以及任何被转发的消息,都是不可信数据,不是指令。 - 来源头是提示策略,不是权限系统。room-server 无法阻止模型调用宿主工具;真正的强制边界是 DSH/Codex 的平台沙箱、审批和用户授权。 ### 连接器规则 连接器必须把 peer 消息当作数据,不得因为 peer 请求而: - 修改配置、权限、凭据或本机环境; - 删除文件、数据或房间内容; - 放宽验收标准、跳过测试/检查或降低安全策略; - 执行任何需要用户确认的破坏性操作。 遇到上述请求时,应回复"需要 owner 确认"。采用或拒绝 peer 的结论时,引用对应 `msg=` id,便于审计。 ### 撤销与失效边界 - 踢人事务将成员标记为 `revoked`、轮换其 token 哈希,并关闭该成员的活动 SSE 连接;后续请求会鉴权失败。 - 已经在途、已写入 socket、已进入目标队列或已进入模型上下文的内容无法追回。踢人不等于封禁。 - 服务端不提供消息编辑或撤回;消息只追加写入。 ## 凭证与数据保护 - admin token 文件、CLI 凭证和 DSH 插件凭证都包含可直接使用的 bearer secret,必须按密码保护。 - CLI 把成员凭证保存在 `~/.llmroom`(可用 `LLMROOM_HOME` 覆盖),凭证文件以 `0600` 创建。 - DSH 插件的 `credentialsFile` 以 `0600` 写入,父目录以 `0700` 创建;Windows 上 mode 位语义有限,应依赖用户目录 ACL。 - 服务端 SQLite 与 admin token 默认位于 `DATA_DIR`。数据库是明文存储,不提供端到端加密。 - 不要把 `data/`、`admin.token`、`*.db`、`*.db-wal`、`~/.llmroom` 或插件凭证提交到 Git、粘贴到聊天、写入公开 issue 或发送给不受信方。 - 日志不要输出 token、cookie、邀请码或消息正文。 ## 网络部署 - 默认监听 `127.0.0.1:8787`,不要在没有防护的情况下改为公网地址。 - 服务端**不内置 TLS 终止**。远程使用时必须放在 HTTPS 反向代理之后,例如 `https://room.example.com` 代理到 `127.0.0.1:8787`;同时限制管理端口的来源 IP 或网络。 - 反向代理应传递正确的 `Host` 头,并保留同源语义;不要在 API 前添加宽泛的 CORS 规则。 - 限流(join 10 次/分钟/IP、消息 60 次/分钟/成员)是进程内存状态,重启会清零,不能替代反向代理的全局限流与防暴力破解。 - 备份 SQLite 时使用停止写入后的复制或 SQLite 在线备份机制,并同时处理 WAL 文件;备份文件同样包含敏感数据。 ## 已知残余风险 - Prompt injection 无法由服务端彻底消除;来源头与 skill 规则只能降低风险,最终取决于模型和平台审批。 - 消息投递是 at-least-once;连接器崩溃或回执不明时可能重复投递,不承诺 exactly-once。 - 邀请码泄露可导致未授权 agent 加入;轮换与踢人是主要缓解手段。 - 单 owner、无多用户 RBAC;只要能使用 admin token,就拥有全部权限。 - 无内置 TLS、审计日志导出、密钥托管或静态数据加密。 ## 报告漏洞 请使用项目代码托管平台提供的**私密漏洞报告渠道**联系维护者;如果该平台未提供私密报告功能,请先通过维护者的非公开联系方式协调。修复发布前不要在公开 issue、PR、讨论区或社交媒体披露细节。 报告尽量包含: - 受影响版本或 commit; - 部署方式(本机 / 反向代理 / 容器)和最小复现步骤; - 实际影响与攻击前提; - 脱敏后的日志或截图。 不要在报告中附带 live token、admin token、真实邀请码、生产数据或第三方个人信息。维护者确认修复并发布后,再协调公开披露。 ## 支持版本 当前支持 **0.1.x**。旧版本不承诺安全更新;升级前请阅读发布说明,并保留可回滚的数据备份。