Files
Nexus/docs/archive/audits/2026-06-04-phase2-merged.md
T
2026-07-08 22:31:31 +08:00

11 KiB
Raw Blame History

Phase2 P2 合并卷

生成日期: 2026-06-04 · 源文件 9 篇 · 原文 docs/archive/audits/2026-06-04-phase2/

批次索引

audit-phase2-2026-06-04-waveP2-1.md

Phase 2 深审 — Wave P2-1Files / SSH 基础设施)

登记

入口表

Closure 表

len(H)=17, Closure=17

FINDING

无 P0/P1 新 FINDING。

L3 门控(同日记录)

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-2.md

Phase 2 深审 — Wave P2-2sync_v2 全文 + 路径/Shell 依赖)

登记

入口表(sync_v2 全 22 路由)

Closure 表

len(H)=20, Closure=20

FINDING

无 P0/P1 新 FINDING。

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-3.md

Phase 2 深审 — Wave P2-3WebSocket / Dashboard 告警链)

登记

入口表

Closure 表

len(H)=16, Closure=16

FINDING

无 P0/P1 新 FINDING。

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-4.md

Phase 2 深审 — Wave P2-4servers.py 全文)

登记

入口表(servers.py 26 路由)

Closure 表

len(H)=20, Closure=20

FINDING

无 P0/P1 新 FINDING。

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-5.md

Phase 2 深审 — Wave P2-5webssh.py 全文)

登记

入口表

Closure 表

len(H)=17, Closure=17

FINDING

无 P0/P1 新 FINDING。

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-6.md

Phase 2 深审 — Wave P2-6sync_engine_v2.py 全文)

登记

入口表(服务层,经 sync_v2 API 调用)

Closure 表

len(H)=17, Closure=17

FINDING

无 P0/P1 新 FINDING。

DoD

  • len(H) == Closure

验证

audit-phase2-2026-06-04-waveP2-7.md

Phase 2 深审 — Wave P2-7(前端页 5/14

登记

Closure 表

len(H)=13, Closure=13

FINDING

无 P0/P1 新 FINDING。

DoD

audit-phase2-2026-06-04-waveP2-8.md

Phase 2 深审 — Wave P2-8(前端页 5/14

登记

Closure 表

len(H)=11, Closure=11

FINDING

无 P0/P1 新 FINDING。

audit-phase2-2026-06-04-waveP2-9.md

Phase 2 深审 — Wave P2-9(前端页 4/14 + 编排层)

登记

Closure 表

len(H)=5, Closure=5

交叉引用

FINDING

无 P0/P1 新 FINDING。

Closure 摘录(合并)

| SSH | list_remote_directoryls -la | 经 pool + server 凭据 | | H | 文件:行号 | 判定 | 理由 | | H-Auth | sync_v2.py:741614 | SAFE | 22 路由均 Depends(get_current_admin) | | H-Shell | sync_v2.py:156-168 | RISK | rm -rf 删目录;JWT+审计+前端 confirm | | H-Shell | sync_v2.py:156,165,168,223-227 | SAFE | path shlex.quote | | H-Path | sync_v2.py:149-165 | SAFE | normalize_remote_abs_path | | H-Clipboard | sync_v2.py:207-208 | SAFE | assert_clipboard_transfer_safe | | H-Sandbox | sync_v2.py:302,341,413,721 | SAFE | ensure_under_nexus_upload | | H-Source | sync_v2.py:548,1096 | SAFE | FORBIDDEN prefixes + resolve | | H-Audit | sync_v2.py:461-475 | SAFE | 失败 log warning+exc_info,非静默 pass | | H-Upload | sync_v2.py:876-877,977-978 | SAFE | 100MB / 500MB 上限 | | H-ZipSlip | sync_v2.py:1000-1005 | SAFE | assert_zip + is_path_under_prefix | | H-Download | sync_v2.py:1244-1272 | SAFE | 100MB + filename sanitize | | H-Read | sync_v2.py:1322-1326 | SAFE | max_size 来自 payload | | H-Write | sync_v2.py:1394-1414 | SAFE | 5MB + etag 409 冲突 | | H-Chmod | sync_v2.py:1507-1514 | SAFE | recursive policy + test -d | | H-Verify | sync_v2.py:1145-1146 | SAFE | sha256sum 路径 shlex.quote | | H-Path | posix_paths.py:46-59 | SAFE | 禁 .. 与反斜杠 | | H-Path | posix_paths.py:117-136 | SAFE | upload 前缀 + zip-slip | | H-Sudo | remote_shell.py:35-53 | SAFE | bash -c + shlex.quote(command) | | H-Clipboard | remote_path_validation.py:24-33 | SAFE | dest 非源子树 | | H-Parse | unix_ls.py:70-71 | SAFE | 跳过 . .. | | H-WS-Auth | websocket.py:304-311,340-347 | SAFE | 无 token → 4001;无效 → 4401 | | H-WS-Token | websocket.py:366-410 | SAFE | tv/updated_at 与 HTTP JWT 一致 | | H-WS-ADR011 | websocket.py:9,296 | RISK | query JWT;单人运维已接受 | | H-WS-Limit | websocket.py:49-52 | SAFE | MAX_CONNECTIONS=500 | | H-WS-Heartbeat | websocket.py:139-165 | SAFE | 30s ping / 60s zombie | | H-WS-Channel | websocket.py:246-249,531-551 | SAFE | alerts 与 sync 分 channel/manager | | H-WS-Dedup | websocket.py:416-437 | SAFE | Telegram 5min 冷却;WS 仍实时 | | H-WS-Recovery | websocket.py:512-513 | SAFE | recovery 清 cooldown | | H-Frontend-Token | useWebSocket.ts:61 | RISK | URL query token;同 ADR-011 | | H-Frontend-Auth | useWebSocket.ts:114-116 | SAFE | 4001/4401 → forceLogout | | H-Frontend-XSS | useWebSocket.ts:99-102 | SAFE | snackbar 文本插值,无 v-html | | H-Frontend-Singleton | useWebSocket.ts:17-18 | SAFE | 模块级单例;App 统一 connect | | H-Dashboard-Refresh | DashboardPage.vue:393-397 | SAFE | WS alert → reload stats/alerts | | H-Dashboard-API | DashboardPage.vue:302-337 | SAFE | http JWT 拉 stats/alert-history | | H-App-Lifecycle | App.vue:257-259 | SAFE | login connect / logout disconnect | | H-Alert-API | settings.py:768-828 | SAFE | alert-history JWT + 参数化 filter | | H-Auth | servers.py:26×路由 | SAFE | 26 端点均 get_current_admin | | H-Mask | servers.py:1692-1698 | SAFE | password_set / agent key 前缀截断 | | H-Encrypt | servers.py:1096-1099,559-562 | SAFE | Fernet encrypt 入库 | | H-Allowlist | servers.py:1163-1187 | SAFE | UPDATE 字段白名单;agent_api_key 排除 | | H-Reauth | servers.py:1256-1260,1479-1483 | SAFE | agent-key/install-cmd 需当前密码 | | H-Reveal | servers.py:1492-1502 | SAFE | install-cmd 不用全局 API_KEY | | H-AgentKey | servers.py:1282-1288 | SAFE | 生成后 display_once 响应 | | H-Fallback | servers.py:626,1321 | RISK | batch/single install 可回退 settings.API_KEY | | H-Shell | servers.py:631-633,1330-1332 | SAFE | install shlex.quote url/key/port | | H-Sudo | servers.py:36-60 | RISK | 临时 sudoers 白名单;运维必要 | | H-SudoPwd | servers.py:1025-1027 | SAFE | sudo -S 密码走 stdin 非 argv | | H-CSV | servers.py:376-388,445-446 | SAFE | formula injection 防御 + 1MB 上限 | | H-CSV | servers.py:499-501 | SAFE | MAX_IMPORT_ROWS=500 | | H-Batch | servers.py:615,686,772,850 | SAFE | Semaphore(5) 并发上限 | | H-Redis | servers.py:179-201,873-877 | SAFE | 心跳 overlay;失败 log warning | | H-Audit | servers.py: CUD/batch | SAFE | 写操作 AuditLog | | H-Crypto | crypto.py:20-26 | SAFE | 无 ENCRYPTION_KEY 则 RuntimeError | | H-Crypto | crypto.py:52-54 | SAFE | decrypt 失败 raise,非静默 | | H-Capability | files_capability.py:31-39 | SAFE | 只读 probe,无密码回传 | | H-Elevation | files_elevation.py:48-55 | SAFE | apply_files_elevation_payload | | H-Purpose | webssh.py:48-49 | SAFE | 拒绝非 webssh purpose | | H-Bind | webssh.py:106-109 | SAFE | token server_id 须匹配路径 | | H-TV | webssh.py:66-76 | SAFE | tv 校验;legacy updated_at +5s grace | | H-Close | webssh.py:97-104 | SAFE | 缺 token→4001;无效→4401 | | H-Issue | auth.py:334-346 | SAFE | 签发前 JWT + server/domain 校验 | | H-Scope | auth_service.py:455-470 | SAFE | JWT 含 server_id + purpose + tv | | H-Expire | auth_service.py:467 | SAFE | 15 分钟短期令牌 | | H-WSQuery | webssh.py:88, useTerminalSessions:293 | RISK | ADR-011 query token(已接受) | | H-Cred | webssh.py:126-135 | SAFE | key/password 配置检查 | | H-Audit | webssh.py:137-146,353-366 | SAFE | connect/disconnect 审计 | | H-Session | webssh.py:148-157,369-376 | SAFE | SshSession 创建/关闭 | | H-DB | webssh.py:111-158 | SAFE | 长连接前关闭 DB session | | H-Pool | webssh.py:167,337 | SAFE | acquire/release + stale retry | | H-CmdLog | webssh.py:277-290,379-398 | SAFE | Enter 触发;2000 字符截断 | | H-Danger | dependencies.py:167-180 | RISK | 危险命令仅 WARN 不阻断(设计) | | H-Resize | webssh.py:293-296 | SAFE | cols/rows 边界默认 80×24 | | H-Error | webssh.py:171,204 | SAFE | SSH 失败不向客户端泄露栈 | | H-Source | sync_engine_v2.py:72-76,327-330 | SAFE | _nexus_source_path 拒绝系统路径 | | H-Conc | sync_engine_v2.py:38,79-80 | SAFE | MAX_CONCURRENT=10 + min 入参 | | H-DBLock | sync_engine_v2.py:89,149,190 | SAFE | _db_lock 串行写 sync_log/retry | | H-Cancel | sync_engine_v2.py:96-136 | SAFE | Redis cancel flag;失败则继续 push | | H-Retry | sync_engine_v2.py:193-224 | SAFE | 失败自动 pending retry;去重 | | H-Subproc | sync_engine_v2.py:468-473 | SAFE | create_subprocess_exec 参数化 | | H-Shlex | sync_engine_v2.py:456-458 | SAFE | key path shlex.quote | | H-KeyTmp | sync_engine_v2.py:449-455,491-495 | SAFE | 0600 临时 key + finally unlink | | H-Pass | sync_engine_v2.py:440-446 | RISK | sshpass -e/proc 可见(内网运维可接受) | | H-Remote | sync_engine_v2.py:414 | SAFE | normalize_remote_abs_path | | H-Timeout | sync_engine_v2.py:476-482 | SAFE | RSYNC_TIMEOUT+30 kill | | H-Output | sync_engine_v2.py:486-487 | SAFE | stdout/stderr 截断 10KB | | H-Staging | sync_engine_v2.py:498-516 | SAFE | 仅 manual 全成功才 rmtree staging | | H-Preview | sync_engine_v2.py:364-365 | SAFE | verbose 文件列表上限 200 | | H-Audit | sync_engine_v2.py:267-271,380-391 | SAFE | sync_files 审计;失败 log error | | H-TG | sync_engine_v2.py:274-291 | SAFE | Telegram 失败不阻断 | | H-Gather | sync_engine_v2.py:254-265 | SAFE | gather 异常计入 failed | | H-JWT | 各页 http.* | SAFE | 经 @/api JWT 客户端 | | H-WS | DashboardPage:393-397 | RISK | useWebSocket query token(已接受) | | H-Nav | DashboardPage:383-387 | SAFE | server_id 数字 query 路由 | | H-Err | DashboardPage:268-345 | SAFE | load 失败 snackbar | | H-CSV | ServersPage:391-435 | SAFE | import FormDataexport 无密码列 | | H-Batch | ServersPage:325-388 | SAFE | batch 端点 JWTconfirm 删除 | | H-Form | ServersPage:162-176 | SAFE | 凭据经 ServerFormDialog composable | | H-Filter | AlertsPage:150-162 | SAFE | 只读分页 API | | H-Audit | AuditPage:126-141 | SAFE | 只读;normalizeAuditList | | H-TG | SettingsPage:272-275 | SAFE | GET 不返 token 明文;value_set | | H-Reveal | SettingsPage:434-460 | SAFE | API Key/TG reveal 需 current_password | | H-Pw | SettingsPage:339-359 | SAFE | 改密 POST;表单 type=password | | H-TOTP | SettingsPage:362-404 | SAFE | setup/enable/disable 走 auth API | | H-CredList | CredentialsPage:253-255 | SAFE | GET 列表无密码明文 | | H-CredPost | CredentialsPage:323-327 | SAFE | encrypted_pw 仅 POST/PUT | | H-CredEdit | CredentialsPage:306,340,357 | SAFE | 编辑留空不修改 | | H-SSH | CredentialsPage:346-347 | SAFE | 私钥仅提交时传输 | | H-Cron | SchedulesPage:177 | SAFE | cron 正则校验 | | H-Sched | SchedulesPage:173-180 | SAFE | 路径/服务器必填 | | H-Retry | RetriesPage:146 | SAFE | retry POST JWT | | H-CmdView | CommandsPage:139-153 | SAFE | 只读 command-logs/sessions | | H-ScriptExec | ScriptsPage:415-419,463-467 | SAFE | exec 走后端 JWT | | H-Quick | ScriptsPage:459-467 | RISK | 临时命令;后端 check_dangerous | | H-Poll | ScriptsPage:527-528 | SAFE | onUnmounted stopPolling | | H-FilesShell | FilesPage.vue:33-37 | SAFE | 逻辑在 useFilesPageD5 | | H-PushShell | PushPage.vue:105 | SAFE | usePushPageD4 | | H-TermShell | TerminalPage.vue | SAFE | useTerminalSessionsD5 | | H-Login | LoginPage.vue | SAFE | auth.login 内存 tokenD6 | | H-NoStore | 四页 | SAFE | 无 localStorage 存密码 |