Repository navigation
fix(server): revoking a session closes its live connection #13844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,7 +82,12 @@ import { | |
| } from "@t3tools/contracts"; | ||
| import { resolveServerBackgroundActivitySettings } from "@t3tools/shared/backgroundActivitySettings"; | ||
| import { resolveProjectSettings } from "@t3tools/shared/projectSettings"; | ||
| import { HttpRouter, HttpServerRequest, HttpServerRespondable } from "effect/unstable/http"; | ||
| import { | ||
| HttpRouter, | ||
| HttpServerRequest, | ||
| HttpServerRespondable, | ||
| HttpServerResponse, | ||
| } from "effect/unstable/http"; | ||
| import { RpcSerialization, RpcServer } from "effect/unstable/rpc"; | ||
|
|
||
| import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; | ||
|
|
@@ -3888,9 +3893,19 @@ export const websocketRpcRouteLayer = Layer.unwrap( | |
| ), | ||
| ), | ||
| ); | ||
| // Revoking a session ends its live socket too, not just future connects. | ||
| // Otherwise a revoked client keeps working until it reconnects on its own, | ||
| // which over a dropped Tailcat tunnel waits for a heartbeat timeout. | ||
| const sessionRevoked = sessions.streamChanges.pipe( | ||
| Stream.filter( | ||
| (change) => change.type === "clientRemoved" && change.sessionId === session.sessionId, | ||
| ), | ||
| Stream.runHead, | ||
| Effect.as(HttpServerResponse.empty()), | ||
|
Comment on lines
+3899
to
+3904
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🛡️ Detected with Advanced Tier | 🟠 Major | 🏗️ Heavy lift Authorization Bypass Reachability: External Close the authentication-to-subscription gap. If 🤖 Prompt for AI Agents |
||
| ); | ||
| return yield* Effect.acquireUseRelease( | ||
| sessions.markConnected(session.sessionId), | ||
| () => rpcWebSocketHttpEffect, | ||
| () => Effect.raceFirst(rpcWebSocketHttpEffect, sessionRevoked), | ||
| () => sessions.markDisconnected(session.sessionId), | ||
| ); | ||
| }).pipe( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟠 High
src/ws.ts:3899A session revoked after
authenticateWebSocketUpgradebut beforesessionRevokedsubscribes remains usable, so the socket continues serving RPCs despiteclientRemoved. Becausesessions.streamChangesis non-replaying and the intervening connection, analytics, and RPC setup yields, that revocation event is lost; subscribe before accepting the connection and pair it with an authoritative revoked-state check to close the subscribe-to-check race.🤖 Copy this AI Prompt to have your agent fix this: