13 KiB
13 KiB
Problems
Findings from systematic bug-hunt and test expansion (May 2026).
Verification: test.bat from project root, or go test ./... in server/agent and npm test in server/web. AI handler only: cd server && go test ./internal/api/... -run AI -v.
Open
Critical / security
- [CRITICAL] server/internal/api/router.go — Unauthenticated build downloads (
/api/v1/builds/{id}/download,/artifact/). Intentional for agent reinstall (UUID is secret). Suggested fix: optional auth toggle or short-lived signed URLs. - [CRITICAL] server/internal/api/websocket.go — Agent WebSocket (
/ws/agent) accepts connections without fleet secret when server secret is unset (first-run). With secret configured, bad secret is rejected; agent can still pick anyagent_id. Suggested fix: bindagent_idto fleet secret baked into forged binary (S2 from prior audit). - [CRITICAL] server/internal/api/ai_handler.go — Unauthenticated AI endpoints (
/agent/decide,/report,/heartbeat); SSRF via caller-supplied Ollama URL. Suggested fix: require fleet secret or dashboard auth. - [HIGH] server/internal/api/router.go — Plaintext passwords in
users.json; any authed user can POST/users. Suggested fix: bcrypt-only storage (partially done), restrict user management to admin role. - [HIGH] server/internal/api/fleet_handler.go — Remote code execution via authenticated API (
powershell/exec/upload). By design — treat dashboard login as root.
High
- [HIGH] server/internal/api/fleet_handler.go —
upload_logreturns content in tool report only; no dedicated log ingest API. - [HIGH] agent/ —
AutoSpreadruns when bakedtruein forge; dangerous if enabled on non-owned fleets. - [HIGH] agent/ — Process hollowing with
-tags hollow+ forge flag; bounds/reloc issues inhollow_windows.go.
Medium / UX
- [MEDIUM] server/web — Compact agent list default; expand on click.
- [MEDIUM] server/web — Remote actions disabled unless
online(by design). - [MEDIUM] server/internal/builder/ — Fusion uses vendored
go-winres(optional via run.bat). - [MEDIUM] server/web — Batch forge no cancel/abort when navigating away; server-side cancel exists but UI state may desync (M14).
- [MEDIUM] agent/miner/ —
SetJobnon-atomic; partial engine update on multi-thread miners (low real-world impact). - [MEDIUM] server/internal/db/sqlite.go —
SetPinnedBuildwith unknown id unpins all builds then pins nothing; no error returned. - [MEDIUM] server/web/src/pages/AgentsPage.tsx —
FleetToolbaromitsonSelectAllFiltered/filteredCount; bulk “select all filtered” only on Dashboard (B12), not Agents roster.
Low
- [LOW] server/internal/api/fleet_handler.go — Package-global
xmrPriceCacheshared across requests/tests; no per-server isolation if multiple routers in one process (unlikely in production). - [LOW] server/web/src/types/ws.ts + server/internal/api/ws_types.go — WS payloads typed in two places; drift risk.
- [LOW] tests/ — No integration tests for remote actions end-to-end.
- [LOW] agent/ — Mesh P2P requires build tag
p2p. - [LOW] server/config.go —
LoadConfiguses legacymergeConfig(notmergeConfigExplicit); a hand-editedconfig.jsonomitting bool fields can still zero them on restart. - [LOW] server/internal/api/config_handler.go —
ConfigHandler.dbis unused; handler delegates entirely toConfigProvider. - [LOW] server/main.go —
UpdateConfigFromJSONhas no semantic validation (negative ports, empty pool host, etc.); invalid values persist to disk. - [LOW] server/internal/db/agent_meta.go —
decodeTagssilently drops invalid JSON intagscolumn (corrupt values become empty slice). - [LOW] server/web/e2e/smoke.spec.ts — E2E login still uses hardcoded
drjones/czapiewski; fails against first-run randomadminpassword. Suggested fix: seedusers.jsonin E2E fixture or read creds from env. - [LOW] server/web/src/types/index.ts — Interfaces only; no runtime type guards for API JSON (validation ad hoc in components).
- [LOW] server/web/src/api/client.ts —
estimateFusionrequiresprepFilebut has no client-side guard (unlikebuildAgentfusion path); server returns error if missing. - [LOW] server/web/src/pages/SettingsPage.tsx — Calibrate UI lives here (
/settingsroute); no separateCalibratePage.tsx. Form labels lackhtmlFor— a11y follow-up. - [LOW] server/internal/maintenance/retention.go —
os.RemoveAllerrors ignored; failed disk cleanup is silent. - [LOW] server/internal/maintenance/retention.go — Artifact dir removed before
DeleteBuild; if DB delete fails, build row remains without files on disk. - [LOW] server/internal/maintenance/retention.go —
StartRetentionJobsgoroutine has no shutdown hook (acceptable for server process lifetime).
Untested packages (next coverage targets)
- [LOW] server/internal/models/ — No unit tests.
- [LOW] server/internal/ollama/ — No unit tests.
- [LOW] server/internal/sys/ — No unit tests.
- [LOW] server/web/src/components/Charts/GaugeRing.tsx — Center label uses raw
valuewhile SVG arc clamps to 0–100%; negative/over-max inputs show misleading text (e.g.200%). - [LOW] server/web/src/help/settingHelp.ts —
FIELD_HELP.walletstill says "~95 characters"; validator accepts 90–106 (same drift fixed in forgeCompatibility / cheatSheetContent troubleshoot).
Fixed (this session)
- server/internal/api/websocket.go —
checkDashboardWSTokencompared plain password to bcrypt hash; dashboard WS auth failed after user migration. Now usescheckPassword. - server/internal/api/ — Added unit/integration tests for remaining handlers:
handlers.go(agent/build REST),router.go(auth middleware, users, rotate-secret, SPA/dropper routes),websocket.go(agent/dashboard WS, fleet secret, max agents, log tail),dropper_handler.go,blueprint_handler.go,ws_types.go. New files:router_test.go,dropper_handler_test.go,blueprint_handler_test.go,websocket_test.go,ws_types_test.go; expandedhandlers_test.go.go test ./internal/api/...— 159 tests PASS. - server/web/src/components/ — Added
components.test.tsx(57 tests) covering all 22 component TSX modules (NeonCard, HelpTip, downloads, ErrorBoundary, SessionGate, charts, fleet panels/toolbar/list/remote actions, forge hints, visual widgets, layout, ambient/matrix/cursor). VitestenvironmentMatchGlobsincludessrc/components/**. - server/web/src/pages/AgentsPage.test.tsx —
AgentRemoteActionsmocked to avoid livelistBuilds/ ECONNREFUSED :3000 in detail-panel tests. - server/web/src/api/client.ts —
fetchJSONspread...optionsafter merged headers could dropContent-TypeandAuthorizationwhen callers passoptions.headers; headers now merged after rest spread. - server/web/src/api/ — Added
client.test.ts(19) anddownload.test.ts(6): paths, query params, auth headers, FormData fusion builds, error bodies. Expandedauth.test.ts(+1 sessionStorage throw path). - server/web/src/context/ — Added
WebSocketContext.test.tsx(2),WebSocketProvider.test.tsx(8),ForgeContext.test.tsx(4): mock WebSocket connect URL/token, message handlers,_seqring buffer, reconnect timer, forge state machine. - server/web/src/pages/BuilderPage.tsx — Load failure no longer stuck on “Loading forge defaults…” when
formis null; error message shown instead. Wallet placeholder/short-wallet hint aligned to 90–106 chars. ExportedformatByteshelper. - server/web/src/pages/SettingsPage.tsx — Wallet placeholder aligned to 90–106 chars. Exported
deepMergehelper (config import). - server/web/src/pages/ — Added
BuilderPage.test.tsx(13) andSettingsPage.test.tsx(11, Calibrate UI at/settings). Page suite now 4 files / 46 tests. - server/web/src/test/fixtures.ts — Added
mockServerConfig()for page/API tests. - server/internal/api/config_handler.go — PUT errors return valid JSON;
invalid config:maps to HTTP 400; GET sets explicit 200. - server/config.go —
mergeConfigExplicittracks nested key presence; partial PUT{"server":{"dashboard_subtitle":"x"}}no longer resets sibling booleans (H14 nested shallow-merge). - server/internal/api/config_handler_test.go — 10 handler unit tests (GET/PUT, 405, invalid JSON, 400/500 paths, JSON escaping).
- server/config_test.go — 9
mergeConfigExplicitregression tests (partial PUT, nested merge, defaults, bool false, fallback). - server/internal/maintenance/ — Added
retention_test.go(12 tests):StartRetentionJobsno-op/disabled, immediate run, 6h tick interval, stats/build purge via temp sqlite + filesystem, zero-retention skips, closed-DB error logs, combined stats+builds pass. Coverage ~97%. ExportedretentionTickInterval+runRetentionFnhooks for testability only. - server/web/src/pages/AgentsPage.tsx — Bulk command errors now alert user (parity with Dashboard B13).
- server/web/src/pages/DashboardPage.tsx — Share log table uses composite React key when
share.idabsent; exportedformatShareTimehelper. - server/web/src/pages/AgentsPage.tsx —
listAgentsno longer overwrites live WS agent list when socket already connected (isConnectedRefguard). - server/web/src/pages/ — Added
DashboardPage.test.tsx(11) andAgentsPage.test.tsx(11); vitest config extended for.tsx+@testing-library/react. - server/internal/db/retention.go —
ListBuildsOlderThanused a partial column list; now usesbuildSelectCols+scanBuildfor consistent fullBuildRecordfields. - server/internal/api/integration_test.go — Integration tests used stale hardcoded
drjones/czapiewskicredentials; server now generates randomadminpassword on first run. Tests seed deterministicusers.jsonbefore router init. - server/web/src/help/fleetAnalytics.ts —
contributionBarsincluded offline agents in total hashrate denominator, skewing contribution percentages on the dashboard. - server/web/src/pages/SettingsPage.tsx — Access Control help text still referenced removed default credentials; updated to describe first-run console password.
- server/internal/api/ai_handler_test.go — Expanded unit tests for
HandleDecide,HandleReport,HandleHeartbeat, engine lifecycle, numeric constants (1000 report cap, 60s heartbeat, 120-char reasoning truncate), Ollama-failure sleep fallback, event broadcaster,recordActivitymerge. - server/internal/api/fleet_handler_test.go — Unit tests for all exported
FleetHandlermethods (GetAlerts,GetPoolStatus,GetAIActivity,GetXMRPrice,GetEarnings/GetEarningsEstimate,GetAgentLog,PostAgentCommand,PutAgentMeta,PostBulkCommand),EstimateXMRPerDay/parseFloatQuery, earnings/XMR price cache TTLs, SupportXMR field normalization, HTTP error branches (503/502/400), and WS command paths via mock transport + test agent WS. - server/web/src/help/forgeCompatibility.ts — Wallet preflight message said length 95–106 but validator accepts 90–106; message aligned with
looksLikeXMRWallet(). - server/web/src/help/ — Added/expanded vitest coverage:
forgeCompatibility.test.ts(37),forgeRules.test.ts(46),settingHelp.test.ts(8). - server/web/src/help/buildManager.test.ts — 9 tests:
blueprintDiff(added/removed/changed, sort, nested, arrays, empty),buildRequestFromRecordmerge/override. - server/web/src/help/cheatSheetContent.test.ts — 19 tests: pipeline/network/fusion/AI guides,
FORGE_VS_CALIBRATE,TROUBLESHOOTING,ROADMAP_FEATURES,CHEAT_SECTIONSregistry. - server/web/src/help/forgeDefaults.test.ts — 7 tests:
FORGE_BUILD_DEFAULTSshape,forgeDefaultsFromServerpublic URL / pool / sign / obfuscate. - server/web/src/help/remoteActions.test.ts — Expanded to 11 tests:
aggressiveActionHint, spread/mesh gating, legacy undefined caps. - server/web/src/help/cheatSheetContent.ts — Troubleshooting "Shares all rejected" wallet text aligned to 90–106 chars (was stale "95 chars").
- server/web/src/types/index.test.ts — Structural fixture tests for all major exported interfaces (20 tests); documents no runtime type guards.
Fixed (earlier passes)
See git history and prior audit IDs (B1–B42, C1–C6, H1–H8, etc.) in README / tests/README.md.
Recommended next section
- server/web/src/help/settingHelp.ts — align wallet help text to 90–106 chars
- server/web/e2e/smoke.spec.ts — seed first-run admin creds for E2E
- server/internal/models/ — struct/JSON round-trip tests
- Agent WS token auth (S2) — security hardening
Test run snapshot (this session)
| Suite | Result |
|---|---|
server/internal/api/... (full) |
PASS (159 tests) |
server Go tests |
PASS (all packages) |
server/internal/api -run Config |
PASS (13 tests) |
server -run Config|Merge |
PASS (13 tests) |
server/internal/api -run AI |
PASS (17 tests) |
server/internal/api -run Fleet |
PASS (39 tests) |
agent Go tests |
PASS |
server/web vitest (page tests) |
PASS — 4 files, 46 tests |
server/web vitest (api/context/hooks) |
PASS — 6 files, 43 tests |
server/web vitest (components.test.tsx) |
PASS — 1 file, 57 tests |
server/web vitest (full suite) |
PASS — 28 files, 347 tests |
server/web vitest (src/help/) |
PASS — 16 files, 181 tests |