{"id":"CVE-2026-102339","aliases":["EUVD-2026-117078","GHSA-6j3h-rp73-6rvf"],"status":"published","title":"Telepresence: Tunnel endpoint accepts caller-supplied session ID with no ownership proof — active client sessions hijackable","description":"Telepresence enables local development against a remote Kubernetes or OpenShift cluster. Prior to 2.31.0, the Traffic Manager Tunnel gRPC streaming endpoint parses a session ID from the first bytes of a caller-controlled message in pkg/tunnel/message.go and passes it to state.Tunnel without verifying that the caller owns the active session. An attacker who obtains a valid active session ID through log leakage, cluster-internal channels, or the unauthenticated ArriveAsClient endpoint can attach a routed tunnel to that session and gain its network routing capabilities. UUID4 session IDs make cold brute force impractical. This vulnerability is fixed in 2.31.0.","severity":{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00287,"percentile":0.21481,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-639"],"published":"2026-11-04T20:35:34Z","modified":"2026-11-09T22:15:03Z","fixes":[{"ecosystem":"Go","package":"github.com/telepresenceio/telepresence/v2","fixed_in":["2.31.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Go","package":"github.com/telepresenceio/telepresence/v2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.31.0"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/telepresenceio/telepresence/v2","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.31.0"}]}]}],"products":[{"vendor":"cisco","product":"telepresence"},{"vendor":"telepresenceio","product":"telepresence"}],"references":[{"url":"https://github.com/telepresenceio/telepresence/security/advisories/GHSA-6j3h-rp73-6rvf","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://github.com/telepresenceio/telepresence/pull/4217","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/telepresenceio/telepresence/commit/1312482488b771742dbedd3015f9a81a27532de6","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/telepresenceio/telepresence/commit/36458b65a010d2b316af48cd90e193ba190785d9","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/telepresenceio/telepresence/releases/tag/v2.31.0","tags":["x_refsource_MISC","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-102339","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-6j3h-rp73-6rvf"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/102xxx/CVE-2026-102339.json","tags":["advisory"]},{"url":"https://github.com/telepresenceio/telepresence","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-102339","title":"Telepresence: Tunnel endpoint accepts caller-supplied session ID with no ownership proof — active client sessions hijackable","description":"Telepresence enables local development against a remote Kubernetes or OpenShift cluster. Prior to 2.31.0, the Traffic Manager Tunnel gRPC streaming endpoint parses a session ID from the first bytes of a caller-controlled message in pkg/tunnel/message.go and passes it to state.Tunnel without verifying that the caller owns the active session. An attacker who obtains a valid active session ID through log leakage, cluster-internal channels, or the unauthenticated ArriveAsClient endpoint can attach a routed tunnel to that session and gain its network routing capabilities. UUID4 session IDs make cold brute force impractical. This vulnerability is fixed in 2.31.0.","status":"published","published":"2026-11-04T20:35:34.03Z","modified":"2026-11-09T16:59:56.924Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-639"],"updated_at":"2026-11-09T17:34:05.130069Z"}],"euvd":[{"id":"EUVD-2026-117078","description":"Telepresence enables local development against a remote Kubernetes or OpenShift cluster. Prior to 2.31.0, the Traffic Manager Tunnel gRPC streaming endpoint parses a session ID from the first bytes of a caller-controlled message in pkg/tunnel/message.go and passes it to state.Tunnel without verifying that the caller owns the active session. An attacker who obtains a valid active session ID through log leakage, cluster-internal channels, or the unauthenticated ArriveAsClient endpoint can attach a routed tunnel to that session and gain its network routing capabilities. UUID4 session IDs make cold brute force impractical. This vulnerability is fixed in 2.31.0.","status":"published","published":"2026-11-04T20:35:34Z","modified":"2026-11-09T16:59:56Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high"}],"updated_at":"2026-11-10T00:18:46.276628Z"}],"ghsa":[{"id":"GHSA-6j3h-rp73-6rvf","title":"Telepresence: Tunnel endpoint accepts caller-supplied session ID with no ownership proof — active client sessions hijackable","description":"## Summary\n\nThe Traffic Manager `Tunnel` gRPC streaming endpoint accepts a session ID from the first bytes of the client-controlled message payload. No verification confirms the caller owns the session. An attacker supplying a valid active session ID receives a fully routed tunnel for that session, gaining the network routing capabilities of the legitimate Telepresence client. Tested on HEAD v2.28.0, commit b2231a4.\n\n## Details\n\nThe `Tunnel` handler reads identity from a client-provided binary payload rather than from a verified credential or prior authenticated gRPC call:\n\n```go\n// cmd/traffic/cmd/manager/service.go:1057-1063\nfunc (s *service) Tunnel(server grpc.BidiStreamingServer[...]) error {\n    stream, err := tunnel.NewServerStream(ctx, tunnel.ClientToManager, server)\n    return s.state.Tunnel(ctx, stream)  // stream.SessionID() is client-controlled\n}\n```\n\n`state.Tunnel` looks up the session ID in the sessions map with no ownership proof:\n\n```go\n// cmd/traffic/cmd/manager/state/state.go:698-703\nfunc (s *State) Tunnel(ctx context.Context, stream tunnel.Stream) error {\n    id := stream.SessionID()   // from client payload bytes\n    if cs, ok := s.clients.Load(id); ok {\n        return s.clientTunnel(ctx, cs, stream)  // full dialer granted\n    }\n    return grpcErrors.Errorf(codes.NotFound, ...)\n}\n```\n\nThe session ID is parsed from the wire message with no binding to the transport-level identity of the caller (pkg/tunnel/message.go:209-214).\n\n## Proof of Concept\n\nPrecondition: a valid active session ID (obtainable via ArriveAsClient, which has no auth either).\n\n```go\nconn, _ := grpc.NewClient(\"traffic-manager.ambassador:8081\",\n    grpc.WithTransportCredentials(insecure.NewCredentials()))\nmgr := rpc.NewManagerClient(conn)\n\ntunnelStream, _ := mgr.Tunnel(ctx)\n\n// Send StreamInfo with victim session ID in payload\ntunnelStream.Send(\u0026rpc.TunnelMessage{Payload: buildStreamInfo(victimSessionID, ...)})\n\n// Traffic Manager routes tunnel traffic for victimSessionID\n// through this attacker-controlled bidirectional stream\n```\n\n## Impact\n\nA caller supplying a valid session ID of an active Telepresence client obtains a tunnel endpoint for that session's network routing context. Session IDs are UUID4s, making cold brute-force impractical; exploitation materialises when session IDs are obtainable via log leakage or cluster-internal channels. Combined with the unauthenticated ArriveAsClient endpoint, an attacker can\ncreate their own sessions and pivot to impersonate active developer sessions.","status":"published","published":"2026-11-09T21:58:00Z","modified":"2026-11-09T21:58:01Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-639"],"updated_at":"2026-11-09T22:20:10.289641Z"}],"nvd":[{"id":"CVE-2026-102339","description":"Telepresence enables local development against a remote Kubernetes or OpenShift cluster. Prior to 2.31.0, the Traffic Manager Tunnel gRPC streaming endpoint parses a session ID from the first bytes of a caller-controlled message in pkg/tunnel/message.go and passes it to state.Tunnel without verifying that the caller owns the active session. An attacker who obtains a valid active session ID through log leakage, cluster-internal channels, or the unauthenticated ArriveAsClient endpoint can attach a routed tunnel to that session and gain its network routing capabilities. UUID4 session IDs make cold brute force impractical. This vulnerability is fixed in 2.31.0.","status":"published","published":"2026-11-04T21:17:40.5Z","modified":"2026-11-12T20:04:52.377Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-639"],"updated_at":"2026-11-09T20:15:34.048597Z"}],"osv":[{"id":"CVE-2026-102339","title":"Telepresence: Tunnel endpoint accepts caller-supplied session ID with no ownership proof — active client sessions hijackable","description":"Telepresence enables local development against a remote Kubernetes or OpenShift cluster. Prior to 2.31.0, the Traffic Manager Tunnel gRPC streaming endpoint parses a session ID from the first bytes of a caller-controlled message in pkg/tunnel/message.go and passes it to state.Tunnel without verifying that the caller owns the active session. An attacker who obtains a valid active session ID through log leakage, cluster-internal channels, or the unauthenticated ArriveAsClient endpoint can attach a routed tunnel to that session and gain its network routing capabilities. UUID4 session IDs make cold brute force impractical. This vulnerability is fixed in 2.31.0.","status":"published","published":"2026-11-04T20:35:34.03Z","modified":"2026-11-11T02:31:01.147209511Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-639"],"updated_at":"2026-11-10T02:45:59.319571Z"},{"id":"GHSA-6j3h-rp73-6rvf","title":"Telepresence: Tunnel endpoint accepts caller-supplied session ID with no ownership proof — active client sessions hijackable","description":"## Summary\n\nThe Traffic Manager `Tunnel` gRPC streaming endpoint accepts a session ID from the first bytes of the client-controlled message payload. No verification confirms the caller owns the session. An attacker supplying a valid active session ID receives a fully routed tunnel for that session, gaining the network routing capabilities of the legitimate Telepresence client. Tested on HEAD v2.28.0, commit b2231a4.\n\n## Details\n\nThe `Tunnel` handler reads identity from a client-provided binary payload rather than from a verified credential or prior authenticated gRPC call:\n\n```go\n// cmd/traffic/cmd/manager/service.go:1057-1063\nfunc (s *service) Tunnel(server grpc.BidiStreamingServer[...]) error {\n    stream, err := tunnel.NewServerStream(ctx, tunnel.ClientToManager, server)\n    return s.state.Tunnel(ctx, stream)  // stream.SessionID() is client-controlled\n}\n```\n\n`state.Tunnel` looks up the session ID in the sessions map with no ownership proof:\n\n```go\n// cmd/traffic/cmd/manager/state/state.go:698-703\nfunc (s *State) Tunnel(ctx context.Context, stream tunnel.Stream) error {\n    id := stream.SessionID()   // from client payload bytes\n    if cs, ok := s.clients.Load(id); ok {\n        return s.clientTunnel(ctx, cs, stream)  // full dialer granted\n    }\n    return grpcErrors.Errorf(codes.NotFound, ...)\n}\n```\n\nThe session ID is parsed from the wire message with no binding to the transport-level identity of the caller (pkg/tunnel/message.go:209-214).\n\n## Proof of Concept\n\nPrecondition: a valid active session ID (obtainable via ArriveAsClient, which has no auth either).\n\n```go\nconn, _ := grpc.NewClient(\"traffic-manager.ambassador:8081\",\n    grpc.WithTransportCredentials(insecure.NewCredentials()))\nmgr := rpc.NewManagerClient(conn)\n\ntunnelStream, _ := mgr.Tunnel(ctx)\n\n// Send StreamInfo with victim session ID in payload\ntunnelStream.Send(\u0026rpc.TunnelMessage{Payload: buildStreamInfo(victimSessionID, ...)})\n\n// Traffic Manager routes tunnel traffic for victimSessionID\n// through this attacker-controlled bidirectional stream\n```\n\n## Impact\n\nA caller supplying a valid session ID of an active Telepresence client obtains a tunnel endpoint for that session's network routing context. Session IDs are UUID4s, making cold brute-force impractical; exploitation materialises when session IDs are obtainable via log leakage or cluster-internal channels. Combined with the unauthenticated ArriveAsClient endpoint, an attacker can\ncreate their own sessions and pivot to impersonate active developer sessions.","status":"published","published":"2026-11-09T21:58:00Z","modified":"2026-11-09T22:15:03.915094153Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-639"],"updated_at":"2026-11-09T22:41:08.537457Z"}]}}
