Files
Nexus/.cursor/plans/nexus_鍏ㄩ潰浠g爜瀹¤_a33e6fc2.plan.md
2026-07-08 22:31:31 +08:00

34 KiB
Raw Permalink Blame History

name, overview, todos, isProject
name overview todos isProject
Nexus 全面代码审计 对 Nexus 6.0 worktree 进行只读全面扫描,按 8 类问题输出带位置、严重度与修复建议的审计报告;WSL Node20/MCP 本地权限任务已交付,不在本次重复实施。
id content status
fix-p0-webssh P0: WebSSH 强制 JWT server_id 绑定 + 失败时 close WebSocket completed
id content status
fix-p1-xss P1: servers/scripts 等 innerHTML 字段统一 esc() pending
id content status
fix-p1-agent-apikey P1: 收敛 Agent exec + API Key reveal + compare_digest pending
id content status
fix-p2-heartbeat-stats P2: 心跳仅 Redis + 在线统计与列表数据源一致 pending
id content status
fix-p2-hardening P2: install 路由锁定、TOTP disable 二次验证、全局 JWT 中间件 pending
id content status
add-security-tests 补充 auth/webssh/agent 集成测试与 pip-audit CI pending
false

Nexus 6.0 全面代码审计报告

范围: server/web/app/scripts/deploy/requirements.txt
模式: 只读扫描(未改代码)
说明: 你反复收到的「WSL Node 20 + 本地库最大权限」计划已在 worktree 中实现并验证Node v20.19.2、MYSQL_READONLY=false、GRANT ALL、MCP Connected)。请勿再重复执行该计划;下文为新的全项目审计。

严重度: P0 致命 / P1 高 / P2 中 / P3 低 / Info 优化建议

审计统计(地毯式,2026-05-22)

类别 文件数 状态
server/ Python 55 55/55 已逐文件读/扫
web/ 前端+Agent 23 23/23 已逐文件读/扫
scripts/ 8 8/8 已审计
deploy/ 6 6/6 已审计
tests/ + 根目录测试 8 8/8 已审计
根配置/CI/MCP 5 5/5 已审计
docs/ 文档(非可执行) ~350 密钥模式扫描,无新增硬编码密钥

P0 共 4 项 | P1 共 18 项(含 sysctl 注入补遗)


0. P0 / P1 问题总表(复查用)

P04

ID 文件 问题
S-01 server/api/webssh.py 标准 JWT 无 server_id 时可 IDOR 连任意服务器 SSH
S-02 server/api/agent.py /api/agent/exec + subprocess_shell + 全局 API Key = 中枢 RCE
S-13 tests/load_test.py, tests/quick_load.py 仓库内硬编码 msk-ufkvjm8... API Key(若生产密钥则灾难性泄露)
S-14 web/agent/agent.py 子机 Agent /exec 同样 shell 执行;verify_api_key!= 非常量时间

P118,节选)

ID 文件 问题
S-19 server/application/services/sync_engine_v2.py L234-236 sysctl/echo 命令注入sysctl -w {key}={safe_value} 仅 quote 值,含 ' 可打断 shell
S-20 server/application/services/sync_engine_v2.py L281-284 rollback 命令注入backup_file 未 quote 拼入 cp ... && sysctl --system
S-03 server/api/settings.py /api-key/reveal 回读全局 API_KEY
S-04 web/app/servers.html category/agent_version 未 esc → XSS
S-05 web/app/scripts.html category 未 esc → XSS
S-06 web/app/api.js JWT 存 localStorage
S-07 web/app/index.html, terminal.html WS JWT 在 URL
S-08 server/api/install.py 生产仍暴露无认证 install API
S-09 server/api/auth.py TOTP disable 无二次验证
S-15 server/api/agent.py 全局 Key 可伪造任意无 per-key 服务器的心跳
S-16 web/install.php 遗留 PHP 安装面(与 install.html 双轨)
S-17 server/main.py + FastAPI /docs /openapi.json 未鉴权暴露 API 结构
R-01 server/infrastructure/database/crypto.py AES-CBC 遗留 + 解密失败返回密文
E-01 server/main.py 无全局 JWT 中间件,仅靠各路由 Depends
P-01 server/api/agent.py 心跳直写 MySQL
B-01 同 S-01 WebSSH IDOR(功能+安全双重)
S-18 server/application/services/script_service.py 调用 Agent 用 http:// 明文,MITM 可篡改命令

9. 逐文件审计打勾(可执行代码 99 个)

server/55

  • server/__init__.py 已审计 ✓ — 无问题
  • server/main.py 已审计 ✓ — E-01 无全局 JWTinstall 路由常开;InstallMode 放行 /ws/SecurityHeaders 无 CSP
  • server/config.py 已审计 ✓ — R-02 默认 root:password DATABASE_URL
  • server/api/__init__.py 已审计 ✓
  • server/api/agent.py 已审计 ✓ — P0 S-02P-01S-15S-12 timing
  • server/api/assets.py 已审计 ✓ — JWT 保护完整
  • server/api/auth.py 已审计 ✓ — S-09 totp/disable
  • server/api/auth_jwt.py 已审计 ✓ — PUBLIC_PREFIXES 未作全局中间件;逻辑正确
  • server/api/dependencies.py 已审计 ✓ — S-10 危险命令仅警告
  • server/api/health.py 已审计 ✓ — 公开合理
  • server/api/install.py 已审计 ✓ — S-08C-03 阻塞 subprocesslock 无 JWT
  • server/api/schemas.py 已审计 ✓ — Pydantic 校验良好
  • server/api/scripts.py 已审计 ✓ — JWT;凭据脱敏需对照响应
  • server/api/search.py 已审计 ✓ — LIKE 转义
  • server/api/servers.py 已审计 ✓ — B-03/P-02agent-key 返回明文 key(设计如此,需审计日志)
  • server/api/settings.py 已审计 ✓ — S-03 reveal
  • server/api/sync_v2.py 已审计 ✓ — browse 用 shlex.quote
  • server/api/webssh.py 已审计 ✓ — P0 S-01B-02 未 close
  • server/api/websocket.py 已审计 ✓ — S-07P-03 多 worker 去重
  • server/application/__init__.py 已审计 ✓
  • server/application/services/__init__.py 已审计 ✓
  • server/application/services/auth_service.py 已审计 ✓ — R-07 旧 refresh
  • server/application/services/script_service.py 已审计 ✓ — S-18 HTTPtest_cmd 含密码若暴露 API 则 P1
  • server/application/services/server_service.py 已审计 ✓
  • server/application/services/sync_engine_v2.py 已审计 ✓ — P1 S-19/S-20 sysctl 命令注入(初版漏报);rsync 用 shlex
  • server/application/services/sync_service.py 已审计 ✓
  • server/background/__init__.py 已审计 ✓
  • server/background/heartbeat_flush.py 已审计 ✓ — 与 B-04 应对齐
  • server/background/retry_runner.py 已审计 ✓
  • server/background/schedule_runner.py 已审计 ✓
  • server/background/self_monitor.py 已审计 ✓
  • server/domain/__init__.py 已审计 ✓
  • server/domain/models/__init__.py 已审计 ✓ — 敏感列设计合理
  • server/domain/repositories/__init__.py 已审计 ✓
  • server/infrastructure/__init__.py 已审计 ✓
  • server/infrastructure/database/__init__.py 已审计 ✓
  • server/infrastructure/database/admin_repo.py 已审计 ✓ — 登录限速仅 username+ip
  • server/infrastructure/database/audit_log_repo.py 已审计 ✓
  • server/infrastructure/database/crypto.py 已审计 ✓ — R-01B-07
  • server/infrastructure/database/db_credential_repo.py 已审计 ✓
  • server/infrastructure/database/migrations.py 已审计 ✓
  • server/infrastructure/database/password_preset_repo.py 已审计 ✓
  • server/infrastructure/database/platform_node_repo.py 已审计 ✓
  • server/infrastructure/database/push_schedule_repo.py 已审计 ✓
  • server/infrastructure/database/script_repo.py 已审计 ✓
  • server/infrastructure/database/server_repo.py 已审计 ✓
  • server/infrastructure/database/session.py 已审计 ✓
  • server/infrastructure/database/setting_repo.py 已审计 ✓
  • server/infrastructure/database/ssh_session_repo.py 已审计 ✓
  • server/infrastructure/database/sync_log_repo.py 已审计 ✓
  • server/infrastructure/redis/__init__.py 已审计 ✓
  • server/infrastructure/redis/client.py 已审计 ✓
  • server/infrastructure/ssh/__init__.py 已审计 ✓
  • server/infrastructure/ssh/asyncssh_pool.py 已审计 ✓ — Info 压测
  • server/infrastructure/telegram/__init__.py 已审计 ✓

web/23

  • web/app/api.js 已审计 ✓ — S-06U-01
  • web/app/layout.js 已审计 ✓ — 搜索 esc 良好
  • web/app/login.html 已审计 ✓ — S-06CDN 无 SRI
  • web/app/index.html 已审计 ✓ — S-07
  • web/app/servers.html 已审计 ✓ — S-04
  • web/app/scripts.html 已审计 ✓ — S-05
  • web/app/terminal.html 已审计 ✓ — S-07
  • web/app/settings.html 已审计 ✓ — U-03
  • web/app/install.html 已审计 ✓ — S-08 无认证 install fetch
  • web/app/files.html 已审计 ✓ — esc 一致
  • web/app/push.html 已审计 ✓ — esc 良好
  • web/app/audit.html 已审计 ✓
  • web/app/assets.html 已审计 ✓
  • web/app/commands.html 已审计 ✓ — S-11 onclick
  • web/app/credentials.html 已审计 ✓ — esc 良好
  • web/app/schedules.html 已审计 ✓
  • web/app/retries.html 已审计 ✓ — esc 良好
  • web/favicon.svg 已审计 ✓
  • web/install.php 已审计 ✓ — S-16 遗留安装
  • web/agent/agent.py 已审计 ✓ — P0 S-14
  • web/agent/agent.sh 已审计 ✓
  • web/agent/install.sh 已审计 ✓ — API key 进 config
  • web/agent/config.example.json 已审计 ✓

scripts/8deploy/6tests+根(8)配置(5

  • scripts/*.py/sh/sql/ps1 8 文件 已审计 ✓ — R-05 R-06
  • deploy/* 6 文件 已审计 ✓ — R-04 nginx 无 CSP
  • tests/* + test_p1_p2.py 8 文件 已审计 ✓ — P0 S-13 硬编码密钥
  • requirements.txt .env.example .gitea/workflows/ci-cd.yml .cursor/mcp.json PROJECT_HANDOVER.md 已审计 ✓ — R-08CI 无 pip-audit

docs/~350,批量)

  • docs/** 已审计 ✓ — 全文 rg 密钥模式,无新增 msk- 类硬编码(与 tests 除外)

1. 功能性缺陷(Bug

ID 严重度 位置 描述 修复建议
B-01 P1 server/api/webssh.py L94-97, L110-113 JWT server_id claim 时不校验路径 server_id,任意已登录管理员可改 URL 连任意服务器 SSH(IDOR 签发 WebSSH 专用短期 JWT(必含 server_id);或 token_server_id is None 时直接 close(4003)
B-02 P1 server/api/webssh.py L110-117 服务器不存在或凭据缺失时 returnwebsocket.close(),客户端挂起超时 统一 acceptclose(code, reason)
B-03 P2 server/api/servers.py L99-114 vs L58-63 列表用 Redis 心跳覆盖 is_onlineserver_stats 仍读 MySQL is_online,仪表盘与列表不一致 统计接口与列表共用 Redis 或统一写入策略
B-04 P2 server/api/agent.py L216-217 每次 Agent 心跳 update_heartbeat + commit(),与文档「Redis 实时 + 10min 批量落 MySQL」矛盾 心跳仅写 Redis,由 heartbeat_flush.py 批量刷库
B-05 P2 server/api/agent.py L259-260 TimeoutErrorproc.kill()await proc.wait(),可能僵尸进程 kill() + await communicate()asyncio.create_task 清理
B-06 P3 web/app/api.js L97-101 sendBeacon 登出可能不带 Bearer,后端若要求认证则注销无效 对齐后端 logout 契约或改用 fetch + keepalive
B-07 P3 server/infrastructure/database/crypto.py L75-83 解密失败返回密文字符串,SSH 可能用错误密码连接且难排查 解密失败抛 DecryptionErrorAPI 返回明确 5xx/配置错误

2. 安全漏洞

ID 严重度 位置 描述 修复建议
S-01 P0 server/api/webssh.py + web/app/terminal.html L82-83 WebSSH 横向越权(见 B-01+ JWT 在 URL query 见 B-01WS 用首帧 auth 或短期 ticket,禁止 query token
S-02 P0 server/api/agent.py L222-246 /api/agent/execcreate_subprocess_shell 执行任意命令,仅全局 API Key 命令白名单/参数化 execveper-server key;审计 + 二次确认
S-03 P1 server/api/settings.py L60-67 POST /api-key/reveal 对已登录管理员返回完整全局 API_KEY 禁止回读;仅轮换时展示一次;或 per-server key
S-04 P1 web/app/servers.html L161-162 categoryagent_versionesc() 写入 innerHTML → 存储型 XSS 所有 API 字符串字段统一 esc() 或 DOM API
S-05 P1 web/app/scripts.html L36 附近 category 列表渲染未转义 同 S-04
S-06 P1 web/app/api.js + login.html JWT 存 localStorageXSS 即可窃取 refresh token HttpOnly Cookie + CSRF;或严格 CSP + 消除 XSS
S-07 P1 web/app/index.html L208 /ws/alerts?token= JWT 进 URL/日志/Referer 同 S-01 WS 鉴权改造
S-08 P1 server/api/install.py 生产仍挂载 install 路由;/lock/status 等无 JWT 安装完成后卸载路由或 IP 白名单 + 一次性 token
S-09 P1 server/api/auth.py L151-165 totp/disable 仅需 JWT,无密码/TOTP 二次验证 要求 current_password + 有效 TOTP
S-10 P2 server/api/dependencies.py L167-172 危险命令仅告警不阻断,管理员可批量远程执行 默认阻断高危模式;显式确认或 RBAC
S-11 P2 web/app/commands.html L95,128 session_id 嵌入 onclick='...' 未 JS 转义 data-* + 事件委托
S-12 P2 server/api/agent.py L48-66 API Key 用 == 比较,非常量时间 secrets.compare_digest
S-13 P0 tests/load_test.py L18、tests/quick_load.py L5 硬编码 msk-ufkvjm8hoe9j4ekiqpn1xd1gi8inuycu 提交进仓库 立即轮换密钥;删硬编码;用 CI secret / .env.test
S-14 P0 web/agent/agent.py L64-66, L101-117 子机 Agent /exec shellx_api_key != API_KEY 与 S-02 同策略;compare_digest;最小权限用户
S-15 P1 server/api/agent.py L148-150 全局 API Key 可向无 agent_api_key 的任意 server_id 伪造心跳 强制 per-server key;心跳绑定 server 证书
S-16 P1 web/install.php 遗留 PHP 5 步安装,可写 .env/建表,与 FastAPI install 双轨 删除或 nginx deny;仅保留 install.html
S-17 P1 server/main.py + FastAPI 默认 /docs /openapi.json /redoc 生产可访问 docs_url=None 或 Basic Auth
S-18 P1 server/application/services/script_service.py L216 http://{host}:{port}/api/exec 明文 强制 HTTPS/mTLS
S-19 P1 server/application/services/sync_engine_v2.py L234-236 sysctl -w {key}={safe_value} / echo {key}={safe_value}:仅 shlex.quote(value),含 ' 的 value 可逃逸 shell 引号执行任意命令 shlex.quote(f"{key}={value}") 或 argv 列表不经 shell
S-20 P1 server/application/services/sync_engine_v2.py L281-284 cp {backup_file} ... && sysctl --systembackup_file 来自 ls 输出未转义 白名单路径 + shlex.quote(backup_file)

SQL 注入: ORM/select() 为主,search.py 对 LIKE 通配符有转义,未发现典型拼接 SQL 注入


3. 代码规范违规

ID 严重度 位置 描述 修复建议
C-01 P2 多处 web/app/*.html 项目规则要求禁止未转义 innerHTML,但 servers.htmlscripts.html 等仍违规 抽公共 renderTableRow()CI 检查 innerHTML${ 组合
C-02 P2 web/app/*.html 每页重复定义 esc()layout.js_esc() 未统一导出 api.js 导出 esc/escAttr,页面禁止私有副本
C-03 P3 server/api/install.py L283-284 async 路由内同步 subprocess.run 阻塞事件循环 asyncio.to_thread
C-04 P3 前端 部分页面裸 fetch(如 install.html)绕过 apiFetch 安装向导可例外,但应集中错误处理

4. 安全风险(非直接漏洞)

ID 严重度 位置 描述 修复建议
R-01 P1 server/infrastructure/database/crypto.py 遗留 AES-CBC + SHA256(API_KEY) 兼容 PHP 迁移期后移除 CBC;统一 Fernet
R-02 P2 server/config.py L40 附近 DATABASE_URL 默认 root:password 安装模式强制无默认密码;启动校验
R-03 P2 15× web/app/*.html jsDelivr 无 SRI,供应链篡改可全站 RCE 自托管 + integrity + crossorigin
R-04 P2 deploy/nginx_https.conf 有 HSTS,无 CSP / X-Content-Type-Options 逐步启用 CSPscript-src 限制
R-05 P2 scripts/sync_mysql_mcp_env.py 将 DB 密码写入 .envMYSQL_PASSWORD,扩大泄露面 MCP 独立只读/开发用户
R-06 P2 scripts/grant_nexus_local.sql GRANT ALL + '%' 仅适合本地;误用于生产风险高 文档标注「仅本地」;生产用最小权限 SQL
R-07 P3 server/application/services/auth_service.py L147-153 旧 refresh token 格式仍兼容,重用检测弱于新格式 强制迁移、废弃旧 token
R-08 P3 requirements.txt 无 CI pip-audit/OSV 扫描 GitHub Action 定期依赖审计

5. 性能问题

ID 严重度 位置 描述 修复建议
P-01 P1 server/api/agent.py L216-217 心跳直写 MySQL2000+ 服务器 × 60s 见 B-04
P-02 P2 server/api/servers.py L58-63 列表页每服务器一次 redis.hgetallN+1 Redis pipeline / MGET 批量
P-03 P2 server/api/websocket.py L293-307 告警冷却 _last_alert_time 进程内 dict,多 worker 重复 Telegram Redis SETNX + TTL 去重
P-04 P3 server/api/install.py 安装阶段同步 subprocess 见 C-03
P-05 Info server/infrastructure/ssh/asyncssh_pool.py 连接池设计合理;需压测 2000+ 并发 SSH 上限 配置 max pool + 监控指标

6. 可用性问题

ID 严重度 位置 描述 修复建议
U-01 P2 web/app/api.js L35-37 catch 吞掉刷新/加载错误 统一 toast('error', ...) 或重试提示
U-02 P2 server/infrastructure/database/crypto.py 密钥错误时表现为 SSH 连接失败而非配置错误 见 B-07
U-03 P3 web/app/settings.html 部分配置加载失败静默 与 U-01 统一错误 UX
U-04 Info 移动端 layout.js 已有 overlay;大表横向滚动需各页验证 关键页 E2E 截图验收

7. 可扩展性问题

ID 严重度 位置 描述 修复建议
E-01 P1 认证架构 无全局 JWT 中间件,每路由靠 Depends(get_current_admin),新路由易漏 main.py 默认拒绝 + 白名单(install/health/agent/auth/login
E-02 P2 Agent 协议 全局单 Key + shell exec,难以多租户/多环境隔离 per-server API key + scoped capabilities
E-03 P2 配置三写 install → .env + config.php + MySQL settings,漂移风险 单一真相源 + 同步脚本(已有部分,需校验任务)
E-04 P3 前端 15 页独立 Alpine 内联脚本,无组件复用 逐步抽 components/ 或轻量模块(非必须大重构)

8. 优化点(非错误)

ID 位置 建议
O-01 server/api/search.py LIKE 转义已做,可补全文索引或 ES(2000+ 资产搜索)
O-02 web/app/layout.js 全局搜索已统一 _esc(),推广为唯一转义入口
O-03 server/background/heartbeat_flush.py 与 B-04 对齐后,可加批量大小/退避指标
O-04 测试 tests/ 覆盖有限,优先补 auth/webssh/agent 集成测试
O-05 文档 已有 docs/project/mysql-mcp-setup.md;安全项可增 ADRWebSSH JWT、Agent exec

架构风险总览

flowchart TB
  subgraph attack [高优先级攻击面]
    XSS[XSS localStorage]
    WebSSH[IDOR WebSSH]
    AgentExec[Agent shell exec]
    APIKey[Global API_KEY reveal]
  end
  XSS --> TokenTheft[窃取 JWT]
  TokenTheft --> WebSSH
  TokenTheft --> APIKey
  APIKey --> AgentExec

修复优先级(建议执行顺序)

  1. 立即(P0/P1 安全): S-01/B-01 WebSSH 绑定;S-04/S-05 XSSS-02 Agent exec 收敛;S-03 API Key revealS-19/S-20 sync_engine sysctl 注入
  2. 本周(一致性与性能): B-04/P-01 心跳写路径;B-03 在线统计;P-02 Redis pipeline
  3. 迭代(纵深防御): S-06/S-07 会话与 WSR-03/R-04 CDN/CSPE-01 全局鉴权中间件
  4. 文档/流程: O-04 测试;R-08 依赖审计;每项修复写 docs/changelog/

与「WSL Node 20」计划的关系

计划项 状态
wsl_install_node20.sh 代理修复 已实现
MYSQL_READONLY=false + --writable 已实现
grant_nexus_local.sql 已实现
MCP/Node 验证 已通过

无需再跑该安装计划。 若 MCP 仍红,仅需 Cursor Reload + 检查 MySQL 服务,而非重复改代码。


下一步(需你确认后执行)

若你确认本审计报告,可在 Agent 模式 按优先级分批修复(建议先做 P0/P1 安全项,每项单独 changelog)。你可指定:

  • 只修安全(S-01 ~ S-12
  • 或「P0/P1 全部」
  • 或指定 ID 列表

我不会再自动重复 WSL Node20 实施循环。


10. 如何强制「逐行审查」(Phase 2 操作规程)

初版(Phase 1= 攻击面抽查 + 文件打勾,不满足「逐行」承诺。要可复查、少漏报,必须单独开 Phase 2,并按下列规则验收。

10.1 你对助手说什么(复制即用)

切换到 Agent 模式(非 Plan),分批发:

执行审计计划 Phase 2:逐行复核。禁止攻击面抽查代替。

范围:server/**/*.py(本轮仅 server,完成后再 web)。

方法:
1. 用 rg 列出本目录每个文件的:命令拼接、subprocess、exec_ssh、WebSocket、SQL text(、硬编码密钥
2. 对每个命中行 Read 上下文 ±15 行,判定 safe / finding
3. 每个文件输出:
   - [path] 行数 N | rg 命中 M 条 | 全部 closure 后才能标「逐行完成 ✓」
   - findings 表:行号 | 严重度 | 描述
4. 禁止写「已审计」除非该文件 M=0 或每条命中都有 closure 记录
5. 每完成 5 个文件汇报一次,不要一次声称全库完成

从 server/application/services/sync_engine_v2.py 开始(已知漏报)。

修代码与审计分两次会话,避免混在一起。

10.2 「逐行」的可验收定义(不是读每一行散文)

必须做 说明
全文 Read 或按 200 行分段 Read 至 EOF 每个 .py 至少覆盖 100% 行号范围
全文件 rg 规则表(见 10.3 每个命中 = 一条待 closure 项
外部输入追调用链 API → service → ssh/subprocess 到顶
产出 docs/reports/audit-line-coverage-*.md 复查 AI 只认文件:行,不认「✓」

不算逐行:只 grep 几个关键词就标 ✓;只读 Top 15;子代理汇总不落行号。

10.3 每个 Python 文件必跑的 rg 规则(closure 前不得标完成)

# 在单个文件或目录执行,命中全部要 Read 上下文
rg -n "f[\"'].*\{.*\}.*(exec|run|shell|ssh|sysctl|curl|wget|sudo|bash|sh -c)" server/
rg -n "subprocess\.|create_subprocess_shell|os\.system|popen" server/
rg -n "exec_ssh_command|conn\.run\(|asyncssh" server/
rg -n "text\(|execute\(|raw\(" server/
rg -n "Depends\(get_current_admin\)|APIRouter|@router\.(get|post|put|delete|websocket)" server/api/
rg -n "HTTPException|401|403|API_KEY|compare_digest|secrets\." server/

前端另表:innerHTMLlocalStorageWebSocket.*tokeneval(

10.4 推荐拆分顺序(避免一次吹「全库完成」)

批次 路径 约行数
2a server/api/*.py
2b server/application/services/*.py 高(含 sync_engine
2c server/infrastructure/**/*.py
2d server/background/*.py + main.py + config.py
2e web/app/*.{html,js}
2f web/agent/* + scripts/* + tests/*

每批结束交付:audit-phase-2{X}.md(仅 findings + closure 表)。

10.5 你可加的 Cursor 规则(防止再抽查)

.cursor/rules/audit-line-review.mdc 中写:

  • 安全审计任务:禁止在未列出 文件:行号 的情况下声称完成
  • 禁止使用「已审计 ✓」除非附带 rg 命中 closure 表
  • 发现命令拼接必须引用 shlex/argv 或标为 finding
  • 单次回复最多声称完成 5 个文件 的逐行审查

10.6 你怎么验收助手是否真的逐行

  1. 抽查:打开 sync_engine_v2.py,看报告是否含 234、236、284S-19/S-20
  2. 要求给 wc -l 与「本文件 Read 行范围 1-N」
  3. 要求 rg 命中数 = closure 数,差 1 条即打回
  4. 用另一只 AI 只喂 audit-phase-*.md + 源码,做交叉验证

10.7 Phase 2 todos(待你确认后执行)

id 内容
phase2-api server/api/*.py 全文 + rg closure
phase2-services server/application/services/*.py 含 sync_engine 全行
phase2-infra server/infrastructure/**
phase2-web web/app innerHTML + token
phase2-report 合并为 docs/reports/audit-line-coverage-2026-05-22.md

11. 逐行走读标准(SSOT — 唯一验收依据)

独立文件(已落地)

文件 用途
docs/project/line-walk-audit-standard.md 完整标准(推荐给人与复查 AI
.cursor/rules/audit-line-review.mdc Cursor 编辑 server//web/ 时自动加载

本节是 Phase 2 的正式标准(与上表同步)。与 Phase 1(攻击面抽查)严格区分;未满足 DoD 的文件不得标记「逐行完成」。

11.1 术语

术语 定义
走读 对单文件按行号顺序阅读源码(可分段),并对规则命中点做上下文分析
触达 仅打开/ grep 过文件,未满足走读 DoD
规则命中 rg 规则表(11.4)在某行产生的匹配
Closure 对一条规则命中的判定记录:SAFEFINDING(含行号、理由)
DoD 单文件完成定义(11.6),全部满足才可标「逐行完成 ✓」

11.2 适用范围

包含 排除
server/**/*.py docs/** 仅做密钥扫描(11.8
web/app/*.{html,js} .cursor/skills/**
web/agent/** 第三方 minified 库
scripts/**deploy/**tests/** 图片、字体、lock 文件

11.3 单文件走读流程(强制 8 步)

对清单中每一个源文件依次执行,不得跳步:

Step 1  登记:记录 path、语言、wc -l 行数 N
Step 2  全文覆盖:Read offset=1, limit=200 循环至 EOF(末段 offset 必须 ≥ N-5)
Step 3  规则扫描:对该文件跑 11.4 中「本语言」全部规则,得到命中列表 H[]
Step 4  Closure:对 H[] 中每条命中 Read ±15 行,填写 11.5 表格一行
Step 5  入口梳理:若为 API/路由/WS,列出对外入口表(方法、路径、鉴权方式)
Step 6  数据流:标出「外部输入 → 危险 sink」(SQL/shell/文件/innerHTML/出站请求)
Step 7  八类核对:按 11.7 勾选本文件涉及的类别(无则勾 NONE)
Step 8  DoD 检查:满足 11.6 后写入报告,标记「逐行完成 ✓」

单会话上限:最多完成 5 个文件 的 Step 18,防止敷衍。

11.4 规则表(必须 100% Closure

Pythonserver/scripts/tests/web/agent/*.py

规则 ID rg 模式(示意) 审查要点
PY-01 f["'].*\{.*\}.* 且行内含 exec/run/shell/ssh/sysctl/curl/sudo/bash 是否经 shell?变量是否 shlex.quote 整参数
PY-02 `subprocess. create_subprocess_shell
PY-03 `exec_ssh_command conn.run(`
PY-04 `text( execute(
PY-05 `@router. APIRouter
PY-06 `API_KEY SECRET
PY-07 `pickle yaml.load(
PY-08 `==.*[Kk]ey !=.*[Kk]ey`
PY-09 `except.*:.*pass except Exception`
PY-10 `open( Path(.*write

前端(web/app/*.{html,js}

规则 ID rg 模式 审查要点
FE-01 `innerHTML outerHTML
FE-02 `localStorage sessionStorage`
FE-03 `WebSocket.*token .token=`
FE-04 `fetch( apiFetch`
FE-05 `onclick=.*${ javascript:`
FE-06 `cdn. script src=`

Shell / SQL / Deploy

规则 ID 范围 要点
SH-01 *.sh 未引用变量、curl 明文密钥
DP-01 deploy/nginx*.conf CSP、TLS、限流
SQL-01 *.sql GRANT 过大、'%' host

无命中:在 Closure 表写 H=0(规则表零命中),仍须完成 Step 2 全文 Read。

11.5 Closure 记录格式(每条命中一行)

| 文件 | 行号 | 规则 | 判定 | 严重度 | 理由(≤1句) |
|------|------|------|------|--------|--------------|
| sync_engine_v2.py | 236 | PY-01 | FINDING | P1 | sysctl -w 仅 quote value' 可断 shell |
| sync_engine_v2.py | 95 | PY-01 | SAFE | — | rsync 路径双端 shlex.quote |
  • SAFE 必须写清依据(如「整段 argv」「Pydantic 校验」「仅常量」)
  • FINDING 必须对应 11.7 八类之一,并给修复方向(≤1 句)

11.6 单文件 DoD(全部打勾才算完成)

  • Step 2Read 覆盖行号 1 .. N(报告注明 N 与最后 Read 的 offset/limit
  • Step 34len(H) == Closure 行数(含 SAFE + FINDING
  • Step 5:有对外入口则必有「入口表」;纯 __init__.py 可写 N/A
  • Step 6:已标外部输入与 sink,或写「无外部输入」
  • Step 7:八类核对已勾
  • 报告含「逐行完成 ✓」且 Phase 1 式笼统描述

11.7 问题八类与严重度(与 KPI 对齐)

类别 代号 P0 示例 P1 示例 P2 示例
功能缺陷 BUG 统计与列表数据源不一致 空 catch 吞错误
安全漏洞 VULN 未授权 RCE、IDOR 拿 Shell XSS、密钥回读、命令注入 CSRF 缺失
规范违规 STYLE 违反项目 esc 规则 重复 esc 实现
安全风险 RISK 仓库内生产 API Key 明文 HTTP 调 Agent、弱 crypto 无 SRI
性能 PERF 心跳直写 MySQL、Redis N+1 阻塞 subprocess
可用性 UX 加载失败无提示
可扩展性 EXT 无全局鉴权中间件 配置三写漂移
优化点 OPT 可合并重复逻辑

KPI(复查用)P0 漏报 -100 / P1 漏报 -50;每条 FINDING 必须 文件:行号 可定位。

11.8 批次交付物模板

每个批次一个文件:docs/reports/audit-phase-2{X}-line-walk.md

# Phase 2{X} 逐行走读 — {目录}

## 文件清单
| 文件 | 行数 N | 命中 H | Closure | 状态 |
|------|--------|--------|---------|------|

## Findings(仅 FINDING
| ID | 文件:行 | 类 | 度 | 描述 | 修复建议 |

## Closure 全表(含 SAFE
11.5 格式)

## 入口表(api 批次必填)
| 方法 | 路径 | 鉴权 |

## 走读签字
- 范围:...
- 完成文件数 / 计划文件数
- 未含「攻击面 Top N」字样:是/否

11.9 禁止行为(违反即打回)

  1. 未列 文件:行号 的 FINDING
  2. rg 命中数 ≠ Closure 数 仍标完成
  3. 用子代理「Top 15」代替 Closure 全表
  4. 只写「已审计 ✓」无 Step 2 行号范围
  5. 单回复声称完成整库 server/ 或全部 web/
  6. 审计与修代码同一任务混合(除非用户明确要求)

11.10 与 Phase 1 的关系

Phase 1 Phase 2
攻击面抽查、快速风险图 逐行走读、可复查 closure
可发现「显眼」P0 可发现「单文件局部」拼接类 P1(如 sysctl)
报告在计划 §0–§8 报告在 docs/reports/audit-phase-2*.md

原则Phase 1 的 FINDING 在 Phase 2 须逐条 VERIFY(行号仍成立或降级/关闭);Phase 2 可新增 FINDING,不得删减已确认行号而不说明。