Fix bugs found in full security and stability audit.

Harden artifact paths and fusion uploads, repair pool reconnect and login ID tracking, fix agent/fusion/frontend regressions, and refresh PROBLEMS.md with the full findings list.
This commit is contained in:
drjones
2026-05-29 09:57:22 -07:00
parent e11fb30350
commit f9e26bb1a6
13 changed files with 281 additions and 82 deletions

View File

@@ -1,75 +1,123 @@
# AetherForge — Problem Audit
Findings grouped by severity. Updated after bug-sweep pass.
Findings grouped by severity. Updated after full bug-hunt pass (May 2026).
**Last verified:** `go test ./...` in `server/` and `agent/`, `npm run build` in `server/web/`, double-click `run.bat`.
**Last verified:** `go test ./...` in `server/` and `agent/`, `npm test && npm run build` in `server/web/`.
---
## Fixed (recent passes)
## Fixed (this pass)
| ID | Fix |
|----|-----|
| B1 | **Pool jobs stop after disconnect**`readLoop` now waits for reconnect instead of exiting; login tracked by `loginRequestID` not hardcoded `1` |
| B2 | **Fusion upload disk exhaustion**`io.LimitReader` + reject unknown upload size |
| B3 | **Artifact path traversal**`safePathUnderRoot()`; `export_dir` limited to `fusion-deliverables/<title>/`; build ID validated before serve |
| B4 | **Multipart forge without fusion**`prep_exe` only required when `fusion_enabled` |
| B5 | **Build succeeds when DB insert fails** — forge now fails if `InsertBuild` errors |
| B6 | **Query limit DoS** — stats/shares `limit` capped at 1000 |
| B7 | **SPA static `..` traversal** — blocked in router fallback |
| B8 | **React 18 + R3F v9 crash** — pinned `@react-three/fiber@8` / `drei@9` (blank black screen) |
| B9 | **SessionGate stale token on network error** — catch sets `authed=false` |
| B10 | **AgentsPage notes/tags wiped while typing** — drafts sync only on agent switch |
| B11 | **WS reconnect timer stacking** — clear timer + close existing socket before reconnect |
| B12 | **Dashboard bulk select limited to top 12** — “Select all filtered” in FleetToolbar |
| B13 | **Dashboard bulk errors silent** — catch + alert |
| B14 | **AI `restart_miner` missing `.exe`** — normalize image name for taskkill/stat/start |
| B15 | **AI reinstall `http.Get` no timeout** — uses `httpClient` |
| B16 | **Fusion `worker_first` blocked forever** — worker launches async; media runs immediately |
| B17 | **Agent empty `new_job`** — logs error and re-requests job |
| B18 | **Agent WS read deadline**`PongHandler` extends deadline on server ping |
---
## Fixed (earlier passes)
| ID | Fix |
|----|-----|
| C1 | `BroadcastServerLog` on `WSHub` |
| C2 | `EncodeToString` in agent download handler |
| C3 | `AgentRemoteActions` legacy props (`agent`, `compact`) |
| C3 | `AgentRemoteActions` legacy props |
| C4 | `useWebSocket` `latestMessage` + Agents detail wiring |
| C5 | Agent handlers: `ps`, `netstat`, `users`, `software`, `screenshot` |
| C6 | `NewMeshNode(c)` in `NewAgentClient` |
| H1 | WS reconnect: only mark offline if closing conn is still active |
| H2 | WS pre-auth guard on `stats`, `submit_share`, `get_job`, `log_tail`, `command_result` |
| H3 | Share submit via async pool queue + `go proxy.SubmitShare` in read loop |
| H2 | WS pre-auth guard on agent message types |
| H3 | Share submit via async pool queue |
| H4 | Fleet broadcast `all` fails when zero agents connected |
| H5H8 | AI: build ID reinstall, uptime, sleep parse, decide HTTP/error field |
| H10 | Download uses `EncodeToString` |
| H13 | `run.bat` fails on frontend build error; kills stale server before bind |
| M3 | `stats_update` includes memory, uptime, shares (server + web hook) |
| M3 | `stats_update` includes memory, uptime, shares |
| M5 | Removed blocking 800ms sleep in `GetAgentLog` |
| M8 | `GetEngine` lock pattern simplified |
| M10 | CORS: `AllowCredentials: false` with `AllowedOrigins: *` |
| M11 | Blueprint delete returns boolean `success` |
| — | Deleted corrupt empty `server/internal/ollama/main.go` and root `main.go` (broke `go build`) |
| — | Fleet filters, bulk commands, per-agent notes/tags (SQLite) |
| — | Ollama prompt: `reinstall_miner` uses `build_id` |
| — | Forge types/defaults include `process_hollowing`, `mesh_p2p`, `auto_spread` (default false) |
---
## Still open
## Still open — Critical / security
### Critical / security
| ID | Issue | Notes |
|----|-------|-------|
| S1 | **Unauthenticated build downloads** | `/api/v1/builds/{id}/download` and `/artifact/` bypass auth (intentional for agent reinstall — UUID is the secret) |
| S2 | **Unauthenticated agent WebSocket** | `/ws/agent` — any client can claim any `agent_id` |
| S3 | **Unauthenticated dashboard WebSocket** | `/ws/dashboard` — full fleet telemetry without login |
| S4 | **Unauthenticated AI endpoints** | `/api/v1/agent/decide`, `/report`, `/heartbeat` — SSRF via caller-supplied Ollama URL |
| S5 | **Default credentials in source** | `drjones` / `czapiewski` until `data/users.json` exists |
| S6 | **Plaintext passwords** | `users.json` stores cleartext; any authed user can POST `/users` |
| S7 | **Remote code execution via API** | Authenticated users can send `powershell`/`exec`/`upload` to any online agent — by design, treat as root |
| ID | Issue |
|----|-------|
| C7 | Partial — REST `/api/v1` requires basic auth; dashboard WebSocket + SPA are open. Use **Calibrate → Save session login** so fetch calls authenticate. |
| C8 | Unauthenticated remote code execution (`powershell`, `exec`, `upload`) on agents that connect to your server |
---
### High (intentional / deploy-time)
## Still open — High
| ID | Issue |
|----|-------|
| H9 | `upload_log` returns content in tool report only (no dedicated log ingest API) |
| H11 | `AutoSpread` still runs when baked `true` in forge |
| H12 | Process hollowing available with `-tags hollow` + forge flag |
| ID | Issue | Notes |
|----|-------|-------|
| H9 | `upload_log` returns content in tool report only | No dedicated log ingest API |
| H11 | `AutoSpread` runs when baked `true` in forge | Feature-gated but dangerous if enabled |
| H12 | Process hollowing with `-tags hollow` + forge flag | Bounds/reloc issues in `hollow_windows.go` |
| H14 | **Partial config PUT corrupts bools** | `mergeConfig` overwrites `UseTLS`, logging flags, etc. with zero values |
| H15 | **Agent `conn` data race** | `submitShare` reads `c.conn` without mutex |
| H16 | **AI reinstall while running** | `os.Rename` fails on Windows when exe in use |
| H17 | **Pool `requestID` / write races** | Concurrent share submits can interleave Stratum lines |
| H18 | **WS concurrent writes** | Ping loop vs broadcast on same dashboard connections |
### Medium / UX
---
| ID | Issue |
|----|-------|
| M1 | Compact agent list default — expand on click; full detail panel retained |
| M6 | Remote actions disabled unless `status === online` (list, detail, dashboard) |
| M7 | Row click vs button bubbling (compact uses `stopPropagation`) |
| M9 | Fusion uses vendored `go-winres` (module + optional `go install` via run.bat) |
## Still open — Medium / UX
### Low
| ID | Issue | Notes |
|----|-------|-------|
| M1 | Compact agent list default | Expand on click |
| M6 | Remote actions disabled unless `online` | By design |
| M9 | Fusion uses vendored `go-winres` | Optional via run.bat |
| M12 | **Multiple `useWebSocket()` hooks** | Dashboard + Matrix overlay = duplicate connections |
| M13 | **`latestWsMessage` drops rapid results** | Only last message kept; command results can be lost |
| M14 | **Batch forge no cancel/abort** | State updates after navigate away |
| M15 | **Re-forge fusion without re-upload** | `reForgeFromBuild` needs prep file |
| M16 | **Earnings estimator race** | Stale API response can overwrite newer estimate |
| M17 | **`MaxAgents` TOCTOU** | Limit checked before lock on agent WS auth |
| M18 | **`GetAgentLog?refresh=1` blocks** | Up to ~1.8s synchronous sleep per request |
| M19 | **`SetJob` non-atomic** | Partial engine update on multi-thread miners |
| M20 | **Autospread goroutine storm** | Up to ~254 goroutines per /24 sweep |
---
## Still open — Low
| ID | Issue |
|----|-------|
| L1 | Dead CSS `.agent-actions` in `FleetPanels.css` |
| L2 | Duplicate CSS imports on Dashboard/Agents |
| L3 | WS payloads typed in `types/ws.ts` + `api/ws_types.go` (partial — not all message types) |
| L3 | WS payloads typed in two places (`types/ws.ts` + Go) |
| L4 | No integration tests for remote actions |
| L5 | Mesh P2P requires build tag `p2p` for full libp2p |
| L5 | Mesh P2P requires build tag `p2p` |
| L6 | `terminalLog` / `agentLogs` grow without bound |
| L7 | Matrix overlay restarts animation on every share |
| L8 | Settings config import shallow-merge |
| L9 | Blueprint files written mode `0644` |
| L10 | XOR media crypto — weak confidentiality by design |
---
@@ -81,3 +129,13 @@ cd ..\agent && go test ./... && go build .
cd ..\server\web && npm test && npm run build
run.bat
```
---
## Priority for next pass
1. Agent WS token auth (bind `agent_id` to build secret)
2. Dashboard WS auth (match REST Basic auth)
3. Config merge with pointer types / explicit fields
4. Shared WebSocket context (single connection app-wide)
5. Process hollowing bounds + reloc (`hollow_windows.go`)