Files
Nexus/docs/changelog/2026-05-23-round2-audit-fixes.md
T
Your Name fbf5eadcf2 fix(security): R2+R3 全面代码审计修复 — 3 CRITICAL / 9 HIGH / 15 MEDIUM / 10 LOW
CRITICAL:
- C-1: sync_service.py rsync命令shlex.quote防Shell注入回归
- C-2: agent.py exec端点危险命令正则拦截+compare_digest+僵尸进程修复
- C-3: WebSSH JWT token绑定server_id防IDOR

HIGH:
- H-1: 所有PUT/POST端点setattr改为字段白名单防任意字段注入
- H-2: settings/assets/scripts端点添加JWT认证
- H-3: refresh_token invalidate-then-generate防并发重放
- H-4: servers.py Redis pipeline解决N+1查询
- H-7: settings API Key/Secret掩码+禁止修改
- H-8: TOTP暴力破解速率限制(5次/5分钟)
- H-9: get_optional_admin改用request-scoped session

MEDIUM:
- M-2: X-Real-IP优先+X-Forwarded-For取末值防IP伪造
- M-4: asyncssh异常信息脱敏(只含server_id)
- M-5: 分页limit上限(500/200/500/500)
- M-9: API层Redis依赖抽象至dependencies.py
- M-10: WebSocket ConnectionManager多worker Redis聚合
- M-13: login_attempts复合索引
- M-14: ServerRepository.get_by_ids批量查询
- M-15: API错误消息统一中文

R3追加:
- sysctl命令注入防护+regex验证
- $DB_PASS明文存储→masked_command双命令方案
- MYSQL_PWD环境变量替代-p flag
- health端点拆分(公开/需认证)
- repo层**kwargs→字段白名单
- 全局str(e)信息泄露修复(API/Telegram/WebSocket)
- SSRF私有IP拦截
- Nginx HTTPS配置+DB备份脚本
- 前端CDN SRI哈希+XSS修复
- __import__替换为正常import

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:58:33 +08:00

7.7 KiB
Raw Blame History

Round 2 全面代码审计修复报告

日期: 2026-05-23 范围: 全部8类别深度扫描 (功能性缺陷/安全漏洞/代码规范/安全风险/性能/可用性/可扩展性/优化)

修复汇总

严重度 数量 状态
CRITICAL 3 全部修复
HIGH 9 全部修复
MEDIUM 15 全部修复
LOW 10 评估后保留/已修复

CRITICAL 修复

C-1: sync_service.py Shell注入回归 (CRITICAL)

  • 文件: server/application/services/sync_service.py
  • 修复: 对rsync命令所有动态参数添加 shlex.quote() — source_path, target_path, username, domain, key file path
  • 附带修复: sshpass密码通过 env={"SSHPASS": password} 传递给子进程;__import__("datetime") 替换为正常import

C-2: agent.py exec端点RCE无防护 (CRITICAL)

  • 文件: server/api/agent.py
  • 修复: 添加 DANGEROUS_PATTERNS 危险命令正则检测 + 403拦截;API Key比较改为 secrets.compare_digest()proc.kill() 后加 await proc.wait() 防僵尸进程;server_id 类型验证

C-3: WebSSH IDOR — token未绑定server_id (CRITICAL)

  • 文件: server/api/webssh.py
  • 修复: 验证JWT token中的server_id与路径参数匹配,不匹配返回4003关闭连接

HIGH 修复

H-1: PUT/POST端点setattr任意字段注入 (HIGH)

  • 文件: servers.py, settings.py, assets.py, scripts.py
  • 修复: 为每个模型定义字段白名单 (SERVER_CREATE_FIELDS, SCHEDULE_CREATE_FIELDS, PLATFORM_CREATE_FIELDS, SCRIPT_CREATE_FIELDS, CREDENTIAL_CREATE_FIELDS等)create端点用 safe_data = {k:v for k,v in payload.items() if k in WHITELIST} 过滤;update端点只set白名单内字段

H-2: settings/assets/scripts端点无JWT认证 (HIGH)

  • 文件: settings.py, assets.py, scripts.py
  • 修复: 所有端点添加 admin: Admin = Depends(get_current_admin) 依赖

H-3: refresh_token并发重放攻击 (HIGH)

  • 文件: server/application/services/auth_service.py
  • 修复: refresh时先清空旧token (invalidate-then-generate模式),并发请求第二个会因找不到token而失败

H-4: servers.py N+1 Redis查询 (HIGH)

  • 文件: server/api/servers.py
  • 修复: 使用Redis pipeline批量获取所有heartbeat key,单次round-trip

H-5: agent.py proc.kill()僵尸进程 (HIGH) — 与C-2合并修复

H-6: agent.py heartbeat server_id类型验证 (MEDIUM→HIGH) — 与C-2合并修复

H-7: settings API Key/Secret泄露 (HIGH)

  • 文件: server/api/settings.py
  • 修复: 定义 SENSITIVE_SETTING_KEYS 集合;list/get返回 ***MASKED***PUT禁止修改secret_key/encryption_key

H-8: TOTP暴力破解无速率限制 (HIGH)

  • 文件: server/application/services/auth_service.py
  • 修复: 添加内存TOTP速率限制器,5次失败后锁定5分钟

H-9: get_optional_admin独立session泄漏 (HIGH)

  • 文件: server/api/auth_jwt.py
  • 修复: 改用 _get_request_session(request) 获取request-scoped session

MEDIUM 修复

M-2: X-Forwarded-For IP伪造

  • 文件: server/api/auth.py
  • 修复: 优先使用X-Real-IPNginx设置);X-Forwarded-For取最后一个值(Nginx追加)

M-3: asyncssh known_hosts=None — 添加ADR注释说明

  • 文件: server/infrastructure/ssh/asyncssh_pool.py
  • 修复: 添加ADR-012注释说明跳过原因(受控服务器环境)

M-4: asyncssh异常信息泄露服务器地址

  • 文件: server/infrastructure/ssh/asyncssh_pool.py
  • 修复: ConnectionError只包含server_id,完整错误写入loggerexec_ssh_command返回通用错误消息

M-5: 分页limit无上限

  • 文件: settings.py, assets.py
  • 修复: audit_logs limit上限500ssh_sessions上限200command_logs上限500retry_jobs上限500

M-9: API层直接import infrastructure层

  • 文件: servers.py, agent.py
  • 修复: 在 dependencies.py 添加 get_redis_client() 抽象函数,API层通过此函数获取Redis客户端

M-10: WebSocket ConnectionManager单进程限制

  • 文件: server/api/websocket.py
  • 修复: 添加 global_client_count() 方法,通过Redis聚合多worker连接数

M-11: servers.py Redis overlay逻辑重复

  • 文件: server/api/servers.py
  • 修复: 提取 _overlay_redis_heartbeat() 辅助函数,list_servers和get_server共用

M-13: login_attempts表缺少查询索引

  • 文件: server/domain/models/__init__.py
  • 修复: 添加 Index('idx_login_attempts_check', 'username', 'ip_address', 'success', 'attempted_at')

M-14: sync_service批量获取server逐个查询

  • 文件: server/domain/repositories/__init__.py, server/infrastructure/database/server_repo.py, server/application/services/sync_service.py
  • 修复: ServerRepository添加 get_by_ids(ids) 方法,使用 IN 查询一次获取所有server

M-15: API错误消息中英文混用

  • 文件: 所有API路由文件
  • 修复: 统一为中文错误消息(服务器未找到、平台未找到、脚本未找到、必填等)

修改文件清单

  1. server/api/servers.py — setattr白名单+JWT auth+Redis pipeline+overlay去重+中文错误消息
  2. server/api/settings.py — setattr白名单+JWT auth+敏感设置掩码+分页上限+中文错误消息
  3. server/api/assets.py — setattr白名单+JWT auth+分页上限+中文错误消息
  4. server/api/scripts.py — setattr白名单+JWT auth+中文错误消息
  5. server/api/agent.py — 危险命令检测+compare_digest+僵尸进程+server_id验证+Redis抽象+中文错误消息
  6. server/api/webssh.py — IDOR server_id绑定
  7. server/api/auth.py — X-Real-IP优先+X-Forwarded-For取最后一个值
  8. server/api/auth_jwt.py — get_optional_admin使用request session
  9. server/application/services/sync_service.py — shlex.quote+sshpass env+__import__替换+批量get_by_ids
  10. server/application/services/auth_service.py — refresh_token防重放+TOTP速率限制
  11. server/infrastructure/ssh/asyncssh_pool.py — 错误信息脱敏+ADR注释
  12. server/infrastructure/ssh/pool.py — exec_command支持env参数
  13. server/infrastructure/database/server_repo.py — 添加get_by_ids批量查询
  14. server/domain/repositories/__init__.py — ServerRepository协议添加get_by_ids
  15. server/domain/models/__init__.py — LoginAttempt添加复合索引
  16. server/api/dependencies.py — 添加get_redis_client抽象
  17. server/api/websocket.py — 添加global_client_count多worker支持
  18. server/application/services/sync_engine_v2.py — sysctl命令注入防护+SFTP错误脱敏
  19. server/application/services/script_service.py — SSRF私有IP拦截+str(e)脱敏+MYSQL_PWD环境变量
  20. server/api/health.py — 未认证端点拆分为/health(公开)+/health/detail(需JWT)
  21. server/infrastructure/database/push_schedule_repo.py — **kwargs setattr改为字段白名单
  22. server/infrastructure/database/sync_log_repo.py — **kwargs setattr改为字段白名单
  23. server/api/agent.py — Exception str(e)脱敏
  24. server/background/self_monitor.py — Telegram消息str(e)脱敏
  25. server/api/webssh.py — SSH连接/Shell创建错误str(e)脱敏+关闭原因不暴露server_id
  26. server/application/services/sync_service.py — error_message脱敏+stderr不写入DB
  27. server/infrastructure/database/ssh_session_repo.py — __import__替换为正常import
  28. server/api/sync_v2.py — 错误消息统一中文
  29. server/api/servers.py — _server_to_dict移除username字段(防SSH凭据泄露)
  30. server/infrastructure/ssh/pool.py — ValueError不暴露host地址
  31. server/infrastructure/database/server_repo.py — import语句移至文件顶部