harden: gate WebSocket command plane, throttle login, lock down Modbus - #1
Open
kevin00156 wants to merge 1 commit into
Open
harden: gate WebSocket command plane, throttle login, lock down Modbus#1kevin00156 wants to merge 1 commit into
kevin00156 wants to merge 1 commit into
Conversation
The role-password auth only ever guarded HTTP routes, but the one write surface that exists is the WebSocket command plane (machine/axis/production) — so any host that could reach the socket could command the machine regardless of login state. Several supporting weaknesses compounded it. Auth / command plane: - Enforce the login wall on the WS command plane: wsserver.Server now holds an Authorizer and checks a per-command minimum role (machine/production → operator, axis → tuner) on every message. Telemetry stays open; commands do not. auth gains Allows()/SessionRole() and exports Role.Satisfies(). - Audit-log every command attempt (peer, role, type, outcome). - Reject out-of-range axis index instead of silently acking OK. Login hardening: - Per-IP failed-login throttle (lockout after repeated wrong passwords) so bcrypt can't be brute-forced or amplified into CPU exhaustion. - Cap the login body with MaxBytesReader. Transport / server: - Explicit http.Server with ReadHeaderTimeout + IdleTimeout (Slowloris). - Conservative security headers (CSP, nosniff, frame-deny, HSTS under TLS). - Warn loudly when serving plain HTTP (password/cookie in clear). Modbus (auth-less by protocol): - Optional --modbus-allow IP/CIDR allowlist to pin the surface to known SCADA hosts; idle-connection reaping and a concurrent-connection cap. Frontend: - Guard ws onmessage JSON.parse against malformed frames. Adds tests for the WS gate (real round-trip), login throttle, Allows policy, and the Modbus allowlist. Docs updated (backend README security section, systemd unit note). https://claude.ai/code/session_017Ku75qTnU5fdUeAyKCsYv1
kevin00156
enabled auto-merge (rebase)
July 20, 2026 06:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
安全檢視發現:role-password 認證系統其實只擋了 HTTP 路由,但唯一存在的寫入面是 WebSocket 指令面(machine/axis/production)。在修補前,任何能連到該 socket 的主機都能下達機器控制指令,無視登入狀態——前端用
auth.satisfies()鎖分頁只是 UI 障眼法。本 PR 補上這道牆並一併加固周邊弱點。變更內容
🔴 核心漏洞修補 — WebSocket 指令面真正受門禁保護
wsserver.Server新增Authorizer,每條指令訊息依「最低角色」檢查:machine/production→ operator、axis→ tuner(commandRole,可依部署調整)。遙測(讀)維持常開,指令(寫)必須過牆。auth新增Allows()/SessionRole(),並匯出Role.Satisfies(),讓非 HTTP 路徑套用與Wrap完全相同的政策(含 operator 未設定時的 back-compat 放行)。🟡 登入加固
http.MaxBytesReader限制登入 body 大小。🟡 傳輸 / Server
http.Server+ReadHeaderTimeout/IdleTimeout(擋 Slowloris;刻意不設 Read/WriteTimeout 以免砍掉長連線 WebSocket)。🟡 Modbus(協定本身無認證)
--modbus-allowIP/CIDR allowlist,把無認證的 Modbus 面釘在已知 SCADA 主機;空值維持原本「允許所有」以不破壞既定 LAN 拓樸。🟢 前端
ws的onmessage包try/catch,畸形封包不再讓 handler 拋例外。測試
Allows政策、Modbus allowlist。go vet ./backend/...乾淨;go test ./backend/...全綠;GOOS=linux GOARCH=amd64交叉編譯通過;前端npm ci && npm run build通過。待決策(非阻擋)
--modbus-allow或網段層限制。style-src 'unsafe-inline',為相容 Svelte 注入的 scoped style 而保留;若要收緊成 nonce-based 需動到前端 build。https://claude.ai/code/session_017Ku75qTnU5fdUeAyKCsYv1