Files
hms/docs/audits/v2/05-security-performance.md
iven df1d85bfde docs: T40 UI 审计报告 + wiki 更新 + Docker 配置
- T40 UI 审计计划和结果文档(docs/qa/)
- wiki 更新:miniprogram 设计系统合规审计记录 + index 关键数字更新
- 审计 V2 完整报告(docs/audits/v2/)
- 讨论记录文档(docs/discussions/)
- 设计规格和实施计划(docs/superpowers/)
- 角色测试计划和结果(docs/qa/role-test-*)
- Docker 生产部署配置
2026-05-13 23:29:42 +08:00

4.9 KiB
Raw Blame History

V2 审计 — 安全合规与性能审计

日期: 2026-05-04

一、安全审计

S1: SQL 注入防护 — 存在高危漏洞

编号 严重度 问题 位置
SEC-01 patient_id/user_id 通过 format! 拼接进 SQL action_inbox_service.rs:272-306
SEC-01a 迁移种子 SQL 使用 format! 迁移文件(硬编码 UUID风险极低
-- 安全 erp-plugin 动态表操作 sanitize_identifier() 40+ 处调用,覆盖完整

SEC-01 详情:

// action_inbox_service.rs 第 272-306 行
let patient_filter = match &query.patient_id {
    Some(pid) => format!("AND patient_id = '{}'", pid),  // 直接拼接!
    None => String::new(),
};
let assigned_filter = format!("AND f.assigned_to = '{}'", user_id.unwrap()); // 直接拼接!

tenant_id 已正确使用 $1 参数化,但 patient_iduser_id 未参数化。虽然来源是已认证用户的上下文(非直接用户输入),但仍违反安全规范。

修复: 改为 Statement::from_sql_and_values 参数化绑定。

S2: PII 加密覆盖 — 合规

AES-256-GCM + 随机 nonce + v1 前缀 + Zeroizing 密钥。

Entity 加密字段
patient id_number, phone, address, emergency_contact, emergency_phone
family_member phone
doctor_profile license_number
consultation_message content
follow_up_record result, plan, medication_notes
diagnosis note, value
lab_report report_content, conclusion
medication_record note, value

结论: 所有 PII 字段均已加密。解密使用 unwrap_or 降级兼容旧数据。

S3: API Key 安全 (BLE 网关) — 合格

  • 存储: SHA-256 哈希 + 前 8 位前缀双因子
  • 生成: OsRng 32 字节随机密钥
  • 传输: Authorization: Gateway <key>X-Gateway-Key
  • 不足: 代码层未强制 HTTPS需在反向代理层配置 TLS

S4: OAuth 安全 — 部分合规

检查项 状态
scope 验证 合规 — 白名单校验
client_secret 存储 合规 — Argon2 哈希
速率限制 已建模,未强制执行
PKCE 不支持(仅 Client Credentials
redirect_uri 不适用

S5: 多租户隔离 — 合规(有一处增强建议)

  • 应用层: 所有 handler 带 ctx.tenant_id 过滤
  • 数据库层: PostgreSQL RLS 在所有含 tenant_id 表上启用
  • SSE: 验证 event.tenant_id != tenant_id 跳过非本租户事件
  • 不足: FHIR allowed_patient_ids 在 JWT claims 中携带但未在查询层强制执行

S6: 权限码一致性 — 存在缺失

编号 严重度 问题
SEC-02 OAuth 管理 handler5 个端点)未调用 require_permission()

所有其他 53 个 PermissionDescriptor 声明的权限码均有对应 require_permission 调用。

S7: XSS 防护 — 合规

Web 和 MP 中均未发现 dangerouslySetInnerHTMLinnerHTML 使用。

S8: SSE 认证 — 合规

  • AI SSE: JSON POST + TenantContext + require_permission
  • 消息 SSE: JWT ?token=xxx query param 回退 + tenant_id 验证

二、性能审计

P1: N+1 查询 — 低风险

未发现典型 N+1 模式。告警引擎 for rule in rules 循环中有额外 DB 查询,但规则数量通常个位数。

P2: 分页覆盖率 — 高

  • 使用 PaginationParams 的 handler: 11 个文件
  • 自定义分页: alert, action_inbox, patient
  • 无分页: doctors, devices, tags, categories, consents, rules, templates, thresholds通常数据量小

P3: AI 缓存 — 未启用

AnalysisService::find_cached() 方法存在但仅用于测试。生产流程未调用。ai_usage.is_cache_hit 字段已预留。

编号 严重度 问题
PERF-01 AI 分析缓存功能存在但未启用

P4: 索引覆盖率 — 合规

最近 19 个迁移新增 22 个索引,覆盖所有新表。所有新表均含 tenant_id 索引。

P5: 批量操作 — 高效

  • 设备数据: insert_many + ON CONFLICT DO NOTHING
  • 随访: batch_create/assign/complete
  • 插件: batch_delete/update 使用 IN (...)

三、问题汇总

编号 严重度 类型 问题 位置
SEC-01 注入 SQL format! 拼接 patient_id/user_id action_inbox_service.rs:272-306
SEC-02 权限 OAuth handler 缺少 require_permission oauth/handler.rs (5 端点)
SEC-03 越权 FHIR allowed_patient_ids 未在查询层执行 fhir/handler.rs
SEC-04 配置 JWT secret dev fallback 硬编码 oauth/middleware.rs:67
SEC-05 限流 rate_limit_per_minute 已建模未执行 oauth/service.rs
PERF-01 缓存 AI 分析缓存未启用 erp-ai/service/analysis.rs
PERF-02 分页 部分列表端点缺分页 各 handler