fix: enforce WS message size limit + add connection keepalive - #30
Conversation
Reported privately per SECURITY.md (finding VishalRaut2106#3, submitted as separate PR per @VishalRaut2106's direction — VishalRaut2106#1+VishalRaut2106#2 already merged in VishalRaut2106#20). Neither readPump nor writePump ever called conn.SetReadLimit(). Gorilla's default is unlimited message size, so any connected client (host or guest) could send a single oversized WS frame and force the server to allocate memory proportional to that frame via ReadJSON() — a handful of malicious connections repeating this could exhaust server memory. Now capped at 32KB per message. Also adds the standard gorilla ping/pong keepalive pattern (SetReadDeadline + SetPongHandler in readPump, a ticker sending periodic pings in writePump). Without this, a connection that goes silently dead (client sleeps, NAT drops it, no clean TCP close) was never detected — readPump blocked forever on it, leaking the goroutine and Client state. Different root cause from VishalRaut2106#7/VishalRaut2106#8's leak (that was an explicit shutdown-ordering bug; this is network-level dead-connection detection) but touches the same readPump/writePump code, so fixing together per the original report. Adds TestReadPumpEnforcesMessageSizeLimit, confirming the server closes the connection on an oversized frame rather than accepting it.
Checked the error returns on SetReadDeadline/SetWriteDeadline/ WriteMessage calls newly added in this PR (via _ = ...), since those are genuinely new lint debt from this diff. Did NOT touch the pre-existing unchecked conn.Close() pattern used throughout readPump/writePump/handleWebSocket/tests — that predates this PR (confirmed by running golangci-lint against upstream/master directly, which already fails with 8 issues before this diff). Fixing repo-wide pre-existing lint debt is out of scope here; flagging separately in the PR thread.
FeedbackBugs and Security Issues
Performance Bottlenecks
Idiomatic Go Conventions
Robust Error Handling
Suggestions for Improvement
SummaryThe changes address the security and performance issues mentioned in the PR description effectively. The code is well-structured, follows idiomatic Go conventions, and includes robust error handling. The suggestions for improvement focus on adding logging, making the configuration more flexible, and enhancing test coverage. Overall, the changes are a significant improvement to the codebase. |
|
CI's Build & Lint failure isn't from this diff — I confirmed by running I did fix the 6 issues genuinely introduced by this diff (unchecked Left the pre-existing |
Fix for finding #3 from the private security report sent per SECURITY.md submitted as a separate PR per @VishalRaut2106's
direction (findings #1+#2 already merged in #20).
conn.SetReadLimit(). Gorilla's default is unlimited message size, so any connected client could send a single oversized WS frame and force the server to allocate memory proportional to that frame via ReadJSON() a memory-exhaustion DoS vector. Now capped at 32KB per message.Type of change
Checklist
go build ./...passes locallygo vet ./...passes locallyTestReadPumpEnforcesMessageSizeLimit