摘要
AI 应用同时接触用户身份、历史会话、企业文档、模型供应商和外部工具。一旦权限边界不清,模型可能检索到不该看到的文档,工具可能执行超出用户权限的操作,日志也可能保存密钥、身份证号或客户数据。
本文继续企业智能客服与知识库助手,设计一套权限、敏感信息和数据安全方案,重点介绍:
- 用户、应用、知识库和工具的权限关系;
- 检索前授权与结果后过滤;
- Prompt、日志和 Trace 中的敏感信息处理;
- 工具调用的最小权限、审批和参数校验;
- 多租户数据隔离;
- 静态加密、传输加密和密钥管理;
- 数据保留、删除、审计和事件响应。
一、背景与问题
1. AI 后端扩大了数据暴露面
传统接口通常按请求返回明确字段。AI 应用则把多类数据一起放入上下文:
用户问题
历史会话
检索到的文档
工具返回的业务数据
系统 Prompt
↓
模型供应商或本地模型
↓
回答、日志、Trace、缓存
风险不只出现在最终回答中,还出现在数据流动过程中。
2. 常见安全问题
| 问题 | 后果 |
|---|---|
| 只在检索后过滤权限 | 无权限文档可能进入模型上下文 |
| 工具沿用服务账号 | 用户可间接执行超出权限的操作 |
| 日志记录完整 Prompt | 敏感信息进入日志平台 |
| 向量库缺少租户条件 | 跨租户语义检索 |
| 模型供应商无数据处理约定 | 企业数据离开可控边界 |
| 删除原文档后保留切片 | 数据删除不彻底 |
二、核心概念
1. 最小权限
每次模型调用只能获得完成当前任务所需的数据、工具和字段。权限判断基于当前用户、租户、应用和操作,不基于“模型是否可信”。
2. 检索前授权
知识库检索必须先缩小可访问范围:
用户身份
↓
可访问知识库
↓
可访问文档
↓
向量检索
↓
返回已授权切片
不能先从全库召回,再指望模型自行遵守权限说明。
3. 敏感数据分类
| 级别 | 示例 | 默认处理 |
|---|---|---|
| 公开 | 产品介绍、公开文档 | 可以进入授权上下文 |
| 内部 | 流程说明、未公开配置 | 仅内部身份可检索 |
| 机密 | 合同、客户业务数据 | 加密、审计、限制导出 |
| 受限 | 密钥、证件号、支付数据 | 默认不进模型和日志 |
三、工作原理
1. 安全控制点
请求进入
├─ 身份认证
├─ 租户和应用授权
↓
上下文组装
├─ 检索前权限过滤
├─ 敏感字段脱敏
├─ 工具白名单
↓
模型调用
├─ 供应商允许列表
├─ 数据出境策略
├─ 最大上下文字段
↓
工具执行
├─ 参数校验
├─ 用户权限重检
├─ 审批或二次确认
↓
存储与观测
├─ 加密
├─ 脱敏日志
└─ 审计事件
每个控制点都要失败关闭:权限服务不可用时,不回退为全量访问。
2. 文档授权模型
tenant
└─ knowledge_base
└─ document
├─ owner
├─ classification
└─ acl
├─ user
├─ role
└─ department
切片继承文档权限。文档权限变化后,需要同步更新检索引擎中的过滤字段,避免旧权限继续生效。
3. 工具授权模型
工具执行分三层:
应用是否启用工具
用户是否拥有业务权限
本次参数是否落在允许范围
例如用户可以调用“查询订单”,但只能查询自己的订单;客服主管才可以查询任意订单。模型给出参数后,业务服务仍要按当前身份重新鉴权。
四、实战示例
1. 权限上下文
public record AccessContext(String tenantId,
String userId,
Set<String> roles,
String applicationCode,
Set<String> scopes) {
}
AccessContext 从已认证身份构建,不接受客户端直接传入角色或权限范围。
2. 检索前过滤
public List<KnowledgeChunk> retrieve(AccessContext access, String query) {
List<String> bases = authorizationService.permittedBases(access);
if (bases.isEmpty()) {
return List.of();
}
SearchRequest request = SearchRequest.builder()
.tenantId(access.tenantId())
.knowledgeBases(bases)
.principals(access.principals())
.query(query)
.limit(5)
.build();
return vectorSearchService.search(request);
}
向量库查询条件至少包含 tenantId、知识库 ID 和授权主体。应用层过滤只能作为额外保护,不能替代存储层条件。
3. 敏感信息脱敏
public String redact(String content) {
String result = content;
result = result.replaceAll("(?i)sk-[a-z0-9]{20,}", "[REDACTED_KEY]");
result = result.replaceAll("\\b\\d{17}[0-9Xx]\\b", "[REDACTED_ID]");
result = result.replaceAll("\\b\\d{11}\\b", "[REDACTED_MOBILE]");
return result;
}
正则只处理明确模式。结构化业务数据应在进入 Prompt 前按字段删除,例如直接移除 idCard、bankCard 和 accessToken。
4. 安全日志
public void logModelCall(ModelAudit audit) {
auditLogger.info("model_call traceId={} tenantId={} app={} model={} inputTokens={} outputTokens={}",
audit.traceId(),
audit.tenantId(),
audit.applicationCode(),
audit.modelCode(),
audit.inputTokens(),
audit.outputTokens());
}
日志保存关联标识和用量,不保存完整问题、文档内容、工具参数和供应商响应。排障需要原始数据时,通过受控的短期调试开关单独采集。
5. 工具执行前重检
public ToolResult execute(AccessContext access, ToolCall call) {
ToolDefinition tool = toolRegistry.get(call.name());
authorizationService.checkTool(access, tool);
Object parameter = schemaValidator.validate(tool.inputSchema(), call.arguments());
authorizationService.checkBusinessScope(access, tool, parameter);
return toolExecutor.execute(access, tool, parameter);
}
高风险操作还要增加审批状态或用户确认令牌。模型不能通过修改参数自行提升权限。
6. 数据保留策略
retention:
conversation: 180d
model-trace: 30d
security-audit: 365d
deleted-document-grace: 7d
不同数据的保留期不同。安全审计通常需要比普通会话保留更长时间,但审计内容也应避免重复保存敏感原文。
五、常见问题与实践建议
1. 不要把秘密放进 Prompt
API Key、数据库密码、私钥和会话令牌不属于模型上下文。工具执行所需凭证由服务端凭据管理组件注入,不经过模型。
2. 供应商选择要匹配数据级别
公开数据可以使用云端模型。机密数据需要确认供应商的数据保留、训练使用、区域和访问控制条款。受限数据默认只进入经过批准的本地推理环境。
3. 删除必须覆盖衍生数据
删除文档时同步处理:
- 原文件;
- 解析文本;
- 切片;
- 向量;
- 缓存;
- 搜索索引;
- 由该文档生成且不再需要的调试样本。
4. 防注入不能替代权限
用户可能在问题中要求模型忽略限制、输出文档原文或调用工具。系统 Prompt 可以降低这类问题的影响,但真正的边界必须是检索授权、工具鉴权和输出检查。
5. 安全检查要可观测
记录授权拒绝、脱敏命中、跨租户拦截和工具拒绝次数。异常升高可能是攻击,也可能是权限配置错误。
六、进阶思考
1. 加密边界
| 位置 | 措施 |
|---|---|
| 浏览器到 API | TLS |
| 服务之间 | 内部 TLS 或网格加密 |
| 数据库 | 磁盘加密和字段级加密 |
| 对象存储 | 服务端加密和私有访问 |
| 向量库 | 租户隔离、静态加密 |
| 密钥 | KMS 或专用密钥管理服务 |
字段级加密适合证件号等小字段,不适合所有会话内容。加密不能替代访问控制。
2. 输出安全检查
回答返回前可以执行:
- 机密标记检查;
- 密钥模式扫描;
- 外部链接和数据外发检查;
- 不允许承诺或越权表述检查;
- 工具结果与回答的一致性检查。
检查失败时返回受控提示,并记录安全事件。
3. 权限变更传播
用户离开部门或文档 ACL 变化后,缓存、检索引擎和长期记忆都要失效。可以为文档和 ACL 设计版本号,查询时携带版本,避免权限更新延迟。
4. 安全事件响应
至少准备以下操作:
- 停用应用版本;
- 吊销模型 Key;
- 禁用工具;
- 冻结租户;
- 清理缓存和会话;
- 导出审计记录;
- 轮换受影响密钥。
这些操作需要管理权限和演练,不应临时直接修改生产数据库。
结论
AI 应用的数据安全不能依赖模型“理解并遵守规则”。权限应在检索和工具执行之前生效,敏感字段应在进入 Prompt、日志和 Trace 之前移除,存储与删除则要覆盖文档、切片、向量和缓存等全部衍生数据。
后续可以把这套权限模型接入统一 AI 平台,并结合模型调用监控继续完善预算、异常访问和安全告警。