# MeshSafe 策略配置说明 | 项目 | 内容 | |---|---| | 适用对象 | 安全管理员、系统管理员 | | 配置文件 | `config/policy.yaml` | | 生效方式 | 修改后调用 `POST /api/v1/policies/reload` 或重启服务 | | 文档版本 | v1.0 | --- ## 目录 1. [配置总览](#1-配置总览) 2. [字段详解](#2-字段详解) 3. [裁决流程](#3-裁决流程) 4. [调整场景手册](#4-调整场景手册) 5. [校验与错误处理](#5-校验与错误处理) 6. [变更管理](#6-变更管理) --- ## 1. 配置总览 策略文件采用 YAML 格式,路径由环境变量 `MESHSAFE_POLICY_FILE` 指定(默认 `/app/config/policy.yaml`)。 **核心原则:策略与代码分离。** 调整判定规则、阈值、白名单只需修改本文件,不需要重新构建或发布镜像。 ```yaml version: "2026.10.1" description: "MeshSafe 默认全局策略(法院文书摆渡场景)" global: block_score: 70 review_score: [30, 70] engine_failure_mode: fail_closed max_file_size: 52428800 sync_max_size: 52428800 allow_encrypted_archive: false allow_encrypted_document: false allowed_extensions: [ ... ] sandbox_required_extensions: [ ... ] rule_overrides: { ... } notification: { ... } audit: { ... } ``` ### 顶层结构 | 键 | 类型 | 必填 | 说明 | |---|---|---|---| | `version` | string | 是 | 策略版本号,建议用日期格式。写入每条扫描结果 | | `description` | string | 否 | 策略说明 | | `global` | map | 是 | 全局阈值与行为开关 | | `allowed_extensions` | list | 是 | 允许传输的扩展名白名单 | | `sandbox_required_extensions` | list | 否 | 强制走沙箱深检的类型 | | `rule_overrides` | map | 否 | 特定规则的强制处置 | | `notification` | map | 否 | 判定理由的输出控制 | | `audit` | map | 否 | 审计记录内容控制 | --- ## 2. 字段详解 ### 2.1 global #### 2.1.1 `block_score` | 项 | 说明 | |---|---| | 类型 | 整数,0~100 | | 默认 | `70` | | 含义 | 风险评分 **≥ 此值** 时判定为 `malicious`,处置动作为 `reject` | 调整方向:调低 → 更严格(更多文件被拒),调高 → 更宽松(需积累更多信号才拒绝)。 > 注意:单条 `critical` 级信号通常权重已达 50~90,因此 `block_score` 低于 50 时,大量正常文档会因多条低级信号叠加被拒。 #### 2.1.2 `review_score` | 项 | 说明 | |---|---| | 类型 | 数组 `[下界, 上界]` | | 默认 | `[30, 70]` | | 含义 | 评分落在该区间时判定为 `suspicious`,处置动作为 `manual_review`(转人工复核) | **这是误报缓冲的关键参数。** 调整方向:调低下界 → 更多文件进入人工复核(更安全但人工压力大);调高下界 → 更少人工复核(但风险文件可能被直接放行)。 #### 2.1.3 `engine_failure_mode` | 项 | 说明 | |---|---| | 类型 | 字符串 `fail_closed` / `fail_open` | | 默认 | `fail_closed` | | 含义 | 检测引擎不可用时的整体行为 | | 取值 | 行为 | 适用 | |---|---|---| | `fail_closed` | 直接拒绝,并说明引擎不可用 | **生产环境必须使用此项** | | `fail_open` | 放行但标记 | 仅限测试环境 | > 等保三级要求"安全优先",生产环境使用 `fail_open` 会在测评时被判定为不符合项。 #### 2.1.4 `max_file_size` | 项 | 说明 | |---|---| | 类型 | 整数(字节) | | 默认 | `52428800`(50 MB) | | 含义 | 单文件大小上限。超限直接拒绝 | #### 2.1.5 `sync_max_size` | 项 | 说明 | |---|---| | 类型 | 整数(字节) | | 默认 | `52428800`(50 MB) | | 含义 | 同步模式处理的文件大小上限。超限转异步 | 必须 ≤ `max_file_size`。若大于,则会出现"文件本身允许但无法同步处理"的中间态。 #### 2.1.6 `allow_encrypted_archive` / `allow_encrypted_document` | 项 | 说明 | |---|---| | 类型 | 布尔 | | 默认 | `false` | | 含义 | 是否允许加密的压缩包 / 加密的文档 | 加密文件无法被静态分析,**在无法确认内容安全的前提下不应放行**。确需放行时,应配合人工复核流程。 ### 2.2 allowed_extensions 允许传输的扩展名白名单。 ```yaml allowed_extensions: - .docx - .pdf - .xlsx - .jpg - .png - .zip ``` 规则: - 必须以 `.` 开头(小写),否则加载校验失败 - 比较时统一转小写,配置中的大写会被拒绝 - **列表为空表示不限制**,生产环境强烈不建议 - 只校验**顶层文件**的扩展名;归档内的子文件由各自规则判定(受 `rule_overrides` 控制) > 白名单是第一道也是最粗的一道防线。它挡不住"扩展名正确但内容是恶意"的攻击——那是 L1/L2 层的职责。 ### 2.3 sandbox_required_extensions 强制走沙箱异步深检的扩展名。 ```yaml sandbox_required_extensions: - .exe - .msi - .js - .vbs - .iso ``` **当前版本(P3 一期)沙箱未实现**,配置此项的效果是:命中的文件会走异步模式,并在 `meta` 中标注需要深检。P4 阶段接入 CAPE 后无需修改本项。 ### 2.4 rule_overrides 特定规则的强制处置。**这是绕过评分直接裁决的能力**,用于把"一票否决"型规则固化下来。 ```yaml rule_overrides: MRaptorAutoExecSuspicious: action: reject reason: "文档宏具备自动执行且包含可疑行为,按策略直接拒绝" DDEAutoExecution: action: reject reason: "检测到 DDE/DDEAUTO 自动执行字段,按策略直接拒绝" ``` | 字段 | 说明 | |---|---| | `action` | 处置动作,见下表 | | `reason` | 判定理由,可直接展示给用户(支持中文) | **action 取值** | 取值 | 行为 | |---|---| | `pass` | 放行 | | `pass_with_flag` | 放行并标记 | | `manual_review` | 转人工复核(同时把评分提升至 65,确保落入复核区间) | | `reject` | 拒绝 | | `reject_and_notify` | 拒绝并通知(当前实现等同 `reject`) | **生效逻辑** 1. 命中 `rule_overrides` 的规则会**优先于评分**处理 2. 若 `action` 为 `reject` 类 → 立即返回拒绝结论,不再累加评分 3. 若 `action` 为 `manual_review` → 评分提升至 65 并继续后续裁决 **为什么用覆盖而不是纯评分**:像 `PathTraversal`、`DDEAutoExecution` 这类信号,一旦出现就足以判定不可放行,不应依赖其他信号累加来"凑够"阈值。 > 规则名必须与《接口文档》§6 中的 `rule` 字段完全一致,包括大小写。写错不会报错,只是永不生效——因此**每次修改后应实际测试验证**。 ### 2.5 notification ```yaml notification: include_reason: true max_reason_length: 500 ``` | 字段 | 说明 | |---|---| | `include_reason` | 是否在结果中返回判定理由。关闭后 `reason` 为空字符串 | | `max_reason_length` | 理由最大长度,超出截断(末尾加 `...`) | > `include_reason` 只影响**返回给调用方的内容**,不影响审计日志。审计日志始终记录完整信息。 ### 2.6 audit ```yaml audit: log_findings: true log_extracted_paths: true ``` | 字段 | 说明 | |---|---| | `log_findings` | 审计日志中是否记录命中的规则明细 | | `log_extracted_paths` | 是否记录归档内提取出的文件路径 | 关闭 `log_findings` 可显著降低审计日志体积,代价是事后无法还原"当初为什么判定为恶意"。**建议保持开启**。 --- ## 3. 裁决流程 ``` ┌─────────────────────────┐ 检测信号 ────────▶│ 步骤 1:引擎可用性检查 │──▶ 引擎不可用 → fail_closed 拒绝 └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 2:文件大小检查 │──▶ 超限 → 拒绝 └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 3:扩展名白名单 │──▶ 不在清单 → 拒绝 └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 4:加密文件检查 │──▶ 加密且不允许 → 拒绝 └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 5:规则覆盖匹配 │──▶ 命中 reject 类 → 立即拒绝 └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 6:权重累加评分 │ └─────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 步骤 7:阈值映射处置 │ └─────────────────────────┘ ``` ### 3.1 评分计算 ``` score = min(Σ(命中信号的 weight), 100) ``` 已被 `rule_overrides` 处理的信号不重复累加。 ### 3.2 阈值映射 | 评分区间 | verdict | action | |---|---|---| | `score == 0` | `clean` | `pass` | | `0 < score < review_low` | `suspicious` | `pass_with_flag` | | `review_low ≤ score < block_score` | `suspicious` | `manual_review` | | `score ≥ block_score` | `malicious` | `reject` | ### 3.3 权重来源 | 层级 | 典型权重 | |---|---| | L0 结构层 | 10 ~ 50 | | L1 ClamAV | 25 ~ 90 | | L2 文档深度 | 15 ~ 80 | | L2B YARA / 二进制 | 10 ~ 85 | 权重定义在各检测引擎内部,调整权重要改代码——**因此优先用 `rule_overrides` 表达策略意图**,而不是频繁改权重。 --- ## 4. 调整场景手册 ### 4.1 场景:误报过多,业务被阻塞 **症状**:大量正常文档被判为 `manual_review` 或 `reject`。 **排查步骤** 1. 查审计日志,找出被拒文件的命中规则 2. 判断是哪条规则在误报 **处理方式** | 误报来源 | 处理 | |---|---| | 某条规则过于敏感 | 用 `rule_overrides` 将该规则降级为 `pass_with_flag`,并改写 `reason` 说明 | | 阈值过低 | 提高 `review_score` 下界,或提高 `block_score` | | 白名单缺少某类型 | 在 `allowed_extensions` 补充 | | 正常文件确实含宏(如模板文件) | 用 `rule_overrides` 对特定规则放行,**但需评估该文件是否会成为攻击载体** | > 建议不要直接调高 `block_score`——那会让真正的恶意文件更容易通过。优先降级具体规则。 ### 4.2 场景:漏报,需要提升严格度 | 措施 | 配置 | |---|---| | 降低复核门槛 | 调低 `review_score` 下界 | | 直接提高拒绝门槛 | 调低 `block_score` | | 某类风险必须拦截 | 在 `rule_overrides` 中加 `reject` | | 禁用某类可执行文件 | 确认 `allowed_extensions` 中不含该类型 | | 加密文件也拦截 | 保持 `allow_encrypted_*` 为 `false` | ### 4.3 场景:新增业务通道,需要独立策略 **当前版本为全局单策略。** 如需按通道区分,两种做法: **做法 A(不推荐,需改代码)**:在策略中引入 `channels` 段,裁决时按 `channel` 取对应子策略。 **做法 B(推荐,零代码改动)**:在摆渡系统侧做分流。摆渡系统按通道自行维护白名单,检测服务只做统一的恶意性判定。 > 本期方案已确认采用全局策略。通道字段贯穿全链路(数据库、审计日志、API),后续扩展无需重构。 ### 4.4 场景:允许某类加密文件 ```yaml global: allow_encrypted_document: true ``` **同时必须配套**:加密文件无法静态检测,风险由人工复核承担。建议同时把该类文件的处置设为 `manual_review`: ```yaml rule_overrides: PdfEncrypted: action: manual_review reason: "PDF 已加密,无法自动检测,转人工复核" ``` ### 4.5 场景:新增一种文件类型要放行 1. 在 `allowed_extensions` 补充扩展名 2. 确认该类型没有对应的深度检测引擎(否则即使放行也只是"未检测",不是"已检测通过") 3. 若该类型有特殊风险(如脚本类),评估是否需要新增检测规则 --- ## 5. 校验与错误处理 ### 5.1 加载时校验项 策略文件在加载时执行严格校验,**任一项不通过则拒绝加载并保留原有策略**: | 校验项 | 规则 | |---|---| | 根节点类型 | 必须是映射结构 | | `review_score` | 下界必须小于上界 | | `block_score` | 不应低于 `review_score` 上界;须在 0~100 之间 | | `rule_overrides[].action` | 必须是合法动作枚举 | | `allowed_extensions` | 每项必须以 `.` 开头 | | `sync_max_size` | 须 ≤ `max_file_size` | > **为什么校验失败要保留旧策略**:如果加载失败时回退到"默认策略"或"空策略",等于把生产环境的判定逻辑悄悄改掉了,比直接报错危险得多。 ### 5.2 重载失败的表现 ```json { "detail": "策略校验失败: block_score (50) 不应低于 review_score 上界 (70)" } ``` 原策略继续生效。修正后重新调用重载接口。 ### 5.3 常见配置错误 | 错误 | 后果 | 修正 | |---|---|---| | 扩展名写成 `docx`(漏点) | 加载校验失败 | 改为 `.docx` | | 扩展名大写 `.DOCX` | 加载校验失败 | 改为小写 | | `rule_overrides` 规则名拼错 | **静默失效** | 对照接口文档 §6 核对,并实际测试 | | `block_score` 调得极低(如 10) | 正常文件大量被拒 | 回调至 60~80 | | `allowed_extensions` 留空 | 所有类型都被拒 | 补充清单 | > **规则名拼错是唯一会静默失效的配置错误**,务必实测。 --- ## 6. 变更管理 ### 6.1 变更流程 ``` 提出变更 → 安全管理员评审 → 备份当前策略 → 修改配置 → 语法校验(本地) → 重载 → 用样本文件验证 → 记录变更 ``` ### 6.2 变更记录要求 每次策略变更应记录: | 项 | 说明 | |---|---| | 变更时间 | 精确到分钟 | | 变更人 | 姓名与账号 | | 变更内容 | 具体字段的前后值 | | 变更原因 | 业务或安全需求说明 | | 影响评估 | 是否影响在途文件、是否需要通知对接方 | | 验证方式 | 用哪些样本文件验证、结果如何 | ### 6.3 版本追溯 每次扫描结果携带 `meta.policy_version` 与 `meta.policy_sha256`。数据库中保留策略版本快照,可用于**按历史策略复现**某一历史文件的判定结果。 ### 6.4 灰度建议 策略变更影响面大时,建议: 1. 先在测试环境用真实样本文件验证 2. 对比新旧策略的判定差异(可通过 `rescan` 接口批量重跑) 3. 差异符合预期后再在生产重载 --- ## 附录:完整默认策略 见 `config/policy.yaml`。本文档说明各字段含义,实际以配置文件为准。 --- **文档结束** · 配套文档:《总体方案》《接口文档》《等保三级对照表》《运维手册》