Files

95 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 安全 Agent 说明
## 原则
- LLM 输出、SQL、文件名、路径、Host 头、路由参数、第三方回传数据和前端消息都不是可信输入。
- 新接口默认拒绝;先认证、再授权、再校验资源归属,最后执行业务。
- 发现现有绕过路径时优先收敛授权语义,不要只在单个 URL 上打补丁。
- 涉及以下任何区域,必须补充或更新回归测试,并运行 `backend/tests/` 中的相关守卫。
## API 权限
- 使用 `CurrentUser` / `SessionDep` 获取身份和会话,不信任请求体中的用户或工作空间 ID。
- 资源型接口使用 `@require_permissions(...)`,并确认:
- `type` 指向正确资源;
- `keyExpression` 能取到真实资源 ID;
- 列表语义不会被单个资源绕过;
- 管理员、工作空间管理员和普通用户路径都明确。
- 权限表达式引用的参数缺失、解析失败或归属不匹配时必须拒绝,不能回退为直接执行处理函数。
- 子资源归属从服务端记录推导并校验完整关系(如字段 → 表 → 数据源 → 工作空间);请求中的 `ds_id`、`oid` 仅为待校验输入。不能仅验证调用者有权访问所提供的数据源,再按任意表/字段 ID 执行操作。
- 批量接口明确整批拒绝还是仅操作有权记录,并测试混合归属输入;单项、批量、同步、导出等入口应遵循相同授权边界。
- 手写查询归属时,同时校验:
- 资源存在;
- 资源属于当前工作空间;
- 资源属于当前用户或其授权范围;
- 助手上下文没有切换到其他工作空间。
- `oid` 和 `workspace_id` 都表示工作空间 ID;不要把两者当成不同授权域。
- 高级助手动态数据源只允许既有动态类型走动态数据源例外;本地 `CoreDatasource` 仍必须校验工作空间归属。
## SQL 生成与执行
修改主流程时应满足以下安全顺序;需在实际入口和调用链验证,不能把本清单当作现状已安全的证明:
1. 只把允许的表和字段元数据提供给模型;
2. 解析模型返回 JSON 并提取 SQL;
3. 用 `sqlglot` 提取真实表名并排除 CTE 别名;
4. 对照允许表集合拒绝未授权表;
5. 按用户、助手和页面嵌入场景应用行权限或动态 SQL 变换;
6. 校验并保存最终 SQL;
7. 执行最终 SQL 并保存结果。
额外要求:
- 不要信任模型返回的 `tables` 字段替代真实 SQL 解析。
- 行权限拼接沿用白名单逻辑运算符和 `_escape_sql_value`,不要引入新的字符串拼接入口。
- 保持 SQL 行数限制和 `SQLBOT_ALLOW_METADATA_QUERIES` 默认关闭语义;不要为了调试全局开启元数据查询。
- 动态 SQL 生成后仍必须走同一解析、校验和保存路径。
- 数据源连接配置解密只发生在服务端执行路径,不进入日志或 API 响应。
## 认证、Host 与嵌入
- 修改 `backend/main.py` 的中间件顺序时,验证实际请求执行顺序(不能只看注册顺序);`HostValidationMiddleware` 必须在认证/业务使用 Host 前拒绝非法值,并回归预检与正常请求。
- Host 只允许合法域名 / IPv4 / IPv6 形态,不能包含 `/`、`@` 或空白。
- 认证和助手 token 头由后端中间件与前端 request interceptor 处理;不要新增手工传递或复制 token 的路径。
- 页面嵌入协议必须保持:
- 仅 `AssistantModel.type == 4` 可用 embedded 协议;
- 先提取目标助手,再用 `app_secret` 验证签名;
- 管理员账号拒绝通过 embedded token 使用;
- 账号状态和工作空间归属仍需校验。
- 修改助手 `domain`、`app_id`、`app_secret` 或类型时,同时考虑目标系统信任边界和跨工作空间访问。
- 前端 `postMessage` 证书流程不要降级为无请求绑定、无来源约束或永久有效证书。
## 文件与路径
- 不信任上传文件名、扩展名、MIME、sheet 名或用户提供的 `filePath`。
- 上传必须限制类型和大小,落盘使用服务端生成的文件名或 opaque ID。
- 读取用户可控路径前,解析真实路径后用 `os.path.commonpath` 等验证其仍位于允许目录内,或通过已授权的内部 ID 映射路径;不使用字符串前缀判断。校验到打开之间不得允许不可信方替换路径或符号链接。
- 下载前先校验权限和服务端文件实际路径的目录归属,包括符号链接解析;`os.path.basename` 只适合清理下载展示名,`FileResponse` 只负责传输,两者都不能替代路径授权。响应不回显内部绝对路径。
- Excel/CSV 解析错误不能变成可猜测的内部路径信息。
## 前端渲染
- 不直接在组件中调用 axios,避免绕开认证、语言、助手证书和错误处理。
- Markdown 渲染保持 `html: false`,代码高亮必须转义。
- 新增富文本 / HTML 渲染必须走既有安全工具和组件;不要添加未净化 `v-html`。
- 链接、图片和远程脚本必须限制协议和来源,不允许 `javascript:` 或用户控制的服务端地址。
- xpack 静态脚本保留缓存穿透参数和失败处理;不要把商业脚本或密钥复制进前端源码。
## 日志与敏感信息
- 不记录 token、密码、API key、数据源明文连接串、SQL 凭据、助手 secret 或完整敏感配置。
- 异常响应面向用户时使用后端 i18n 错误;内部 traceback 只进入受控日志。
- 安全测试样本可以包含攻击载荷,但不得包含真实可用凭据或内部地址。
## 必测场景
按本次涉及的入口选择相关场景;不要求每次安全改动执行下列全部类别,但必须说明未覆盖的相关风险:
- 未登录、无权限、资源不存在、跨工作空间访问;
- 管理员、工作空间管理员、普通用户、助手用户;
- Host 头携带路径、`@`、空白等污染形态;
- SQL 引用未授权表、CTE 别名、动态 SQL 和行权限边界;
- embedded token 错误助手类型、错误签名、管理员账号和无效账号;
- 上传路径穿越、非法扩展、超限大小和重复扩展名;
- 前端错误传播和未净化内容渲染。