Skip to content

refactor: migrate websocket library from gorilla to coder/websocket - #1906

Merged
Wikid82 merged 6 commits into
developmentfrom
refactor/migrate-coder-websocket
Nov 11, 2026
Merged

Wikid82 merged 6 commits into
developmentfrom
refactor/migrate-coder-websocket

Conversation

@Wikid82

@Wikid82 Wikid82 commented Nov 10, 2026

Copy link
Copy Markdown
Owner

Summary

gorilla/websocket is no longer maintained. This moves both the server side (backend/) and the agent (agent/) to github.com/coder/websocket v1.8.15 in a single PR.

Backend

  • New websocket_upgrade.go centralizes origin checking and the upgrade. The origin rule is unchanged: no Origin, or the origin host must equal Host/X-Forwarded-Host, otherwise 403 before upgrade. Orthrus still accepts any origin (bearer token is the boundary).
  • New log_socket.go shares read-limit, keepalive and write helpers across the logs, cerberus and hecate streams.
  • Stats hub and orthrus server/session ported; the hand-rolled wsNetConn is replaced by websocket.NetConn.
  • Dead code removed (old pong/deadline handling, TCP buffer-shrinking helpers, unused AgentSession.conn).

Agent

  • leash dials with websocket.Dial; wire behavior is preserved: no compression, no proxy, no HTTP/2 negotiation, binary-only NetConn, abrupt close, unchanged headers.

Behavior changes worth reviewing

  • Non-upgrade GETs to the orthrus and cerberus WS endpoints now return 426 instead of 400.
  • The hecate stream now has a ping/pong keepalive and a 10s write deadline; clients that stop answering pings are dropped after about 60s. Its client read limit is now coder's 32 KiB default (clients send nothing).
  • JSON frames no longer end with the trailing newline that gorilla's WriteJSON added.
  • The agent connection carries binary frames only; a text frame closes it (the orthrus server only sends binary).
  • A write that times out now closes the connection (library behavior).

Other

  • Removed the Renovate ignoreDeps entry for the old dependency so the new one is tracked; updated both ARCHITECTURE tables.
  • //nolint:bodyclose on the three websocket.Dial call sites: the library documents that the response body is nil on success and closed on error.

Testing

  • Ported all websocket tests in backend/internal/api/handlers, backend/internal/orthrus and agent/leash; added tests for the upgrade/origin helper, the agent NetConn close behavior, and the dial HTTP client.
  • go build, go vet, and golangci-lint (fast) are clean for both modules.
  • Backend and agent go test pass, and handlers, orthrus, services and the agent pass under -race.
  • Full Playwright / cross-browser runs are left to CI.

Note: one test (the stalled-write test) relies on kernel socket buffers filling within a 10s budget, so it may be timing-sensitive on other hosts.

gorilla/websocket is no longer maintained. Move the backend (log, cerberus,
hecate and stats streams, orthrus server) and the agent (leash) to
coder/websocket v1.8.15.

- Centralize origin checking and upgrade in websocket_upgrade.go; the origin
  rule is unchanged (same host or X-Forwarded-Host, otherwise 403)
- Share read-limit, keepalive and write helpers for log-style sockets
- Hecate stream now gets keepalive and a write deadline
- Agent keeps wire compatibility: no compression, no proxy, no HTTP/2,
  binary-only NetConn, abrupt close
- Non-upgrade requests to WS endpoints now return 426 instead of 400
- Drop the Renovate ignore for the old dependency and update ARCHITECTURE docs
@github-advanced-security

Copy link
Copy Markdown
Contributor

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Supply Chain Verification Results

✅ PASSED

📦 SBOM Summary

  • Components: 1873

🔍 Vulnerability Scan

Severity Count
🔴 Critical 0
🟠 High 0
🟡 Medium 13
🟢 Low 2
Total 16

📎 Artifacts

  • SBOM (CycloneDX JSON) and Grype results available in workflow artifacts

Generated by Supply Chain Verification workflow • View Details

@codecov

codecov Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.49123% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agent/leash/leash.go 92.85% 1 Missing ⚠️
backend/internal/api/handlers/stats_handler.go 50.00% 1 Missing ⚠️
backend/internal/orthrus/server.go 66.66% 1 Missing ⚠️
backend/internal/orthrus/session.go 75.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

With the ACL module on, Cerberus checks the API client IP against every
enabled access list. Several security specs created enabled lists (or hosts
attached to them) and never deleted them, so the next spec that turned the
ACL module on was refused by the leftovers. The GeoIP unenforced-alert spec
hit this after emergency-operations, failed in beforeAll and cleanup, and
left the ACL on for the rest of the run.

Clean up in a finally/afterEach in emergency-operations, acl-creation,
acl-dropdown-regression, acl-waf-layering, acl-enforcement and
access-lists-crud, and add a deleteProxyHostByDomain helper.
The bare .font-mono.text-xs selector also matched the GeoIP database card's
file path on /security, so Playwright's strict mode rejected it. Scope it to
the scrollable log pane.

The live log viewer only renders while Cerberus is on, and the security
shard baseline leaves it off, so the spec's old probe (whose result nothing
read) never skipped or enabled anything. Enable Cerberus for the file and
restore the previous state afterwards.
@Wikid82
Wikid82 merged commit 1703f27 into development Nov 11, 2026
56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants