X-Gortex-Overlay-Session lets a caller name any overlay cohort id, and nothing checks that the caller owns it. Overlay state is unsaved editor-buffer content pushed via overlay_push, so naming another session's cohort reads (and can write) that session's in-flight source.
This is not a regression — the header has always been caller-supplied. PR #649 strictly narrowed it: before that PR the same header also replaced the request's whole session identity (WithSessionID), so it took over tool-policy gating, token accounting, notes scoping and the rest along with the overlay. WithOverlayCohortID reduced its blast radius to overlay selection alone.
Filing it because the narrowing came with a doc comment that now blesses the header as a supported override:
This exists for callers that legitimately want to scope overlay state to a cohort id that differs from their own transport session (e.g. a CI harness that orchestrates several overlay scopes from one connection)
That is a reasonable use case, but as written the mechanism grants it by letting anyone address anyone. Worth deciding deliberately rather than inheriting.
Options
- Namespace cohort ids under the owning session, e.g. store as
<session-id>/<cohort>. The CI-harness case keeps working — one connection, several cohorts — while a different session naming the same cohort string lands in its own namespace and sees nothing.
- Bind on first use: the first session to push under a cohort id owns it; later requests from a different session id are refused.
- Accept it explicitly and say so in the doc comment — that overlay cohorts are a shared namespace with no ownership, so callers must not treat overlay contents as private.
Any of the three is fine; what I would rather avoid is the current state, where the comment reads as a designed feature and the ownership question is simply unaddressed.
Reachable surfaces
X-Gortex-Overlay-Session on POST /v1/tools/{name} (internal/server/handler.go), and the same cohort value reaches overlaySessionID, snapshotOverlayRequestForCtx, prepareOverlayRequest, buildOverlayViewForCtx, and the simulate / explore-literal-overlay call sites.
X-Gortex-Overlay-Sessionlets a caller name any overlay cohort id, and nothing checks that the caller owns it. Overlay state is unsaved editor-buffer content pushed viaoverlay_push, so naming another session's cohort reads (and can write) that session's in-flight source.This is not a regression — the header has always been caller-supplied. PR #649 strictly narrowed it: before that PR the same header also replaced the request's whole session identity (
WithSessionID), so it took over tool-policy gating, token accounting, notes scoping and the rest along with the overlay.WithOverlayCohortIDreduced its blast radius to overlay selection alone.Filing it because the narrowing came with a doc comment that now blesses the header as a supported override:
That is a reasonable use case, but as written the mechanism grants it by letting anyone address anyone. Worth deciding deliberately rather than inheriting.
Options
<session-id>/<cohort>. The CI-harness case keeps working — one connection, several cohorts — while a different session naming the same cohort string lands in its own namespace and sees nothing.Any of the three is fine; what I would rather avoid is the current state, where the comment reads as a designed feature and the ownership question is simply unaddressed.
Reachable surfaces
X-Gortex-Overlay-SessiononPOST /v1/tools/{name}(internal/server/handler.go), and the same cohort value reachesoverlaySessionID,snapshotOverlayRequestForCtx,prepareOverlayRequest,buildOverlayViewForCtx, and the simulate / explore-literal-overlay call sites.