Phase 1a: browser-side security
continuous-integration/drone/push Build encountered an error

- Provider-controlled strings (channel names, groups, file names, log
  lines, in-place mapping edits, client info) are rendered with
  textContent instead of innerHTML. PopupContent.description() takes an
  explicit isHTML flag that only the static help texts pass.
- Websocket: drop the always-true CheckOrigin so gorilla's same-origin
  check applies; read the session token from the HttpOnly cookie sent with
  the handshake (the ?Token= query parameter is still accepted for older
  clients); the client no longer puts the token in the URL, rewrites the
  cookie, or console-logs request/response payloads.
- Session cookie is HttpOnly, SameSite=Strict, Path=/, session-scoped
  (expiry stays server side) and is cleared on logout.
- Serving the first-run wizard no longer sets Settings.AuthenticationWEB
  to false; the wizard page simply bypasses login while it is active.
- Upgrade failures no longer write a second error response.
- Tests: src/websocket_test.go covers cross-origin refusal, same-origin
  and no-Origin clients, missing/unknown/legacy tokens, and cookie flags.
This commit is contained in:
2026-09-26 12:59:47 +10:00
parent 504ea3f9f4
commit 4976219857
8 changed files with 238 additions and 102 deletions
+14 -2
View File
@@ -503,9 +503,21 @@ loopToken:
}
// SetCookieToken : set cookie
// SetCookieToken : sets the session cookie. It is HttpOnly (scripts cannot
// read it), SameSite=Strict, and a session cookie: expiry is enforced server
// side per token and refreshed on every authenticated request. A token of
// "-" clears the cookie (logout).
func SetCookieToken(w http.ResponseWriter, token string) http.ResponseWriter {
expiration := time.Now().Add(time.Minute * time.Duration(tokenValidity))
cookie := http.Cookie{Name: "Token", Value: token, Expires: expiration}
cookie := http.Cookie{
Name: "Token",
Value: token,
Path: "/",
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
}
if token == "-" {
cookie.MaxAge = -1
}
http.SetCookie(w, &cookie)
return w
}