
大模型在知识库问答、客服助手和 Agent 场景落地后往往出现一个尴尬现象Anthropic、Claude、对齐、安全这些词频繁出现在讨论里但开发团队真正花时间处理的却是“模型为什么会说出别的客户的数据”“为什么两个人聊着聊着串了上下文”这类问题。围绕模型越权访问事件的讨论容易让人以为问题出在模型产生幻觉实际上很多越权来自调用链上缺失的认证、授权和资源归属校验一个document_id没有按当前用户过滤一段未做租户隔离的 system prompt一个被客户端直接传入的user_id都足以让 Claude 基于不属于当前用户的数据生成回复。本文不提供对某次具体事件内部结论的猜测也不搬运无法确认的公司公告细节而是把这类事件带给工程团队的方法论讲清楚。以 Claude 模型 API 为例结合 FastAPI 写一个最小可运行的接入层说明越权访问有哪些形态、模型对齐和应用层安全各自负责什么边界、代码上如何防止水平越权和垂直越权。后面还会给出模型连接类报错的排查路径、发布前可复用的安全检查清单以及遇到“回答引用了无权访问的内容”时从哪一层开始定位。1. 先理解大模型场景里的越权访问和传统 Web 越权有什么不同要防御越权不能只记住“越权”两个字。大模型应用里的越权虽然还是“一个用户访问了另一个用户的数据”但访问的形式多了一层模型生成的过程很多问题变得不容易通过页面返回或纯数据库查询发现。1.1 传统 Web 越权的两个基础概念传统 Web 越权通常分两类。水平越权指同一角色的用户访问了不属于自己的资源。例如用户 A 登录后修改 URL 里的订单号结果看到了用户 B 的订单详情。这类问题通常由“服务端只校验了登录态没有校验资源归属”造成。垂直越权指低权限用户执行了高权限操作。例如普通用户可以调用管理员删除接口通常由“接口没有按角色或权限码进行二次校验”造成。大模型应用并没有摆脱这两种风险只是增加了新的表现层。API 接收的不再只是“返回某条订单详情”还可能是“根据某份文档内容回答我的问题”“帮我调用某个工具完成数据变更”。权限判断一旦缺失返回给用户的不再是一段 JSON而是一段由大模型润色过的、看似合理的回答。1.2 模型上下文加入后越权出现了三种新形态在与 Claude 等模型 API 集成的服务里常见的越权形态可以归纳成三类。越权形态典型触发方式表层现象资源越权请求体传入document_id后端直接按 ID 加载内容并注入 prompt模型引用了无权访问的合同、报告或用户资料角色与工具越权Agent 或 function calling 根据用户指令调用删除、发送、修改等函数普通用户通过一句话让模型执行了管理员操作上下文串用同一个缓存键、Redis 会话或长期连接被多个用户复用用户 A 的对话轮次里出现了用户 B 上一轮的输入或结果资源越权在 RAG 类应用中尤其常见。请求流程往往是这样前端传入document_id后端去向量库或文档表取内容再把内容拼接进 system prompt最后交给 Claude 生成回答。如果文档表查询没有加“当前用户是否有可读权限”的条件模型天然会基于“已经传到 prompt 里的内容”作答。它不会像关系型数据库的 SQL 查询那样因为没有权限条件直接报错反而会把数据组织成一段很流畅的回答越权在这里是被模型“加工”过的。1.3 提示词约束靠不住权限必须是确定性代码有些开发团队意识到这个问题后第一反应是在 system prompt 里加一句“你只能回答用户有权限访问的内容”。这句话从技术上没有完全无效但它拦不住真正的越权。原因在于如果后端已经把用户 B 的文档内容拼进 system prompt模型并不知道这段内容来自哪里也无法判断这段内容是否属于当前用户。它看到的是“有一份资料请你基于它回答”然后就会照做。模型输出是概率性生成不是安全沙箱权限判断必须是完全确定的代码逻辑必须发生在数据进入 prompt 之前。这也是理解模型对齐与大模型应用安全关系的关键前提模型层面可以对“说有害内容”进行对齐调整但代码层面如果把无权限的数据直接喂给模型再强的模型对齐也无法在应用层替我们兜底。2. 模型应用的安全边界不能只盯着模型本身很多关于模型越权访问的讨论会自然滑向“模型行为不够安全”这个结论。但从工程实现看一次请求要经过模型服务层和应用层两个完全不同的安全域。两者各有职责不能互相替代。2.1 模型侧的对齐工作在解决什么问题模型对齐是指让模型在训练、微调和部署阶段遵守设计意图尽量避免输出有害内容、非预期指令或偏离任务目标的内容。以 Claude 系列为代表的对话模型发布前会经过大量红队测试和安全评估目标是把“通过概率生成表达出用户不想要的或者有风险的行为”降到可接受范围。但这类对齐发生在模型层面应对的是“模型面对任意输入时输出是否安全”。它不会知道你数据库里哪条合同属于哪个租户也不应该承担这套业务权限判断。模型从 API 收到的输入只有 message、system prompt 和对话历史这些输入本来就是上层应用拼接好的。只要应用层把内容选错模型就会认为这些内容可以被正常引用。2.2 应用侧负责的才是真正的业务安全对大模型应用开发者来说应用侧至少要做四类事。第一身份认证。确认“当前调用者是谁”不能相信客户端传来的user_id字段要通过服务端维护的 token、session 或 OAuth 体系解析用户身份。第二授权判断。确认“当前用户是否有权限访问某个资源”或“当前用户是否有权触发某个工具”。这个判断要在确定性的代码、数据库查询条件或权限服务中完成。第三上下文隔离。进入 prompt 的内容只能来自已经通过授权校验的资源并且会话缓存要按用户维度和租户维度隔离。第四输出与审计保护。对模型输出做必要脱敏或内容过滤记录请求 ID、用户、资源 ID、模型调用结果一旦出现越权或泄露能够回溯整条链路。2.3 责任边界要写在协作约定里Claude API 这类模型服务本身会要求调用方持有 API Key也就是模型服务只负责确认“调用方是不是有资格使用 API 的账号”。至于这个应用里的普通用户是否看过某份文档模型服务并不知道。安全职责负责方说明模型行为对齐、有害内容过滤模型服务商作用于模型输入输出不感知业务资源归属API Key 鉴权模型服务商校验调用方身份不是业务用户身份业务用户认证应用层服务端解析 token不能暴露 API Key 给浏览器或客户端资源授权应用层数据库和权限服务拦截无权访问prompt 内容拼装应用层只向模型提供已授权文档和合法会话上下文工具执行校验应用层每次真实数据变更前都要做后端权限校验日志审计应用层记录链路标识和访问对象敏感内容脱敏这条责任边界一旦被违反往往就会在某个不起眼的地方出现越权。比如有人把 API Key 放到前端直连模型等于把通道级鉴权当成用户级鉴权有人把客户端输入直接拼进 system prompt等于把 prompt 结构化边界让渡给用户。这些问题不解决模型版本升级得再频繁业务越权也依然存在。3. 用 FastAPI 和 Claude API 搭建一个带访问控制的模型调用入口下面用一个模拟企业文档问答助手的代码示例来说明。这里的代码是工程思路演示需要在真实项目中结合自己的目录结构、数据库连接和鉴权方式调整。3.1 环境与依赖准备先确认开发环境已经具备以下条件。组件用途注意事项Python 3.10运行示例低版本可能影响 Pydantic 和 FastAPI 行为