GHSA-g936-7jqj-mwv8: TSDProxy: Internal proxy auth token forwarded to backend services enables management API escalation
Description
A vulnerability was discovered in TSDProxy where it forwards its internal per-process authentication token to all proxied backend services. When identityHeaders is enabled (the default), tsdproxy injects x-tsdproxy-auth-token into every upstream HTTP request alongside user identity headers. This token is the same secret used by the management HTTP server to trust forwarded Tailscale identity claims. A backend that receives this token can replay it from localhost to the management port with an arbitrary x-tsdproxy-id value, bypassing Tailscale authentication entirely.
The token is forwarded unconditionally: ProviderUserMiddleware always calls WhoisNewContext regardless of whether the user is authenticated. In the ReverseProxy.Rewrite function, WhoisFromContext returns ok=true even for zero-value Whois{} (unauthenticated or Funnel requests). The HeaderAuthToken is set for every request when identityHeaders=true.
The attack requires the backend to reach 127.0.0.1:8080. This holds in: (1) non-Docker deployments where tsdproxy and a backend run on the same host, (2) Docker host-network-mode containers, (3) containers sharing tsdproxy's network namespace.
Affected files
- internal/proxymanager/port.go:123-132
- internal/core/admin.go:160-182
// port.go: auth token forwarded regardless of user authentication state
if identityHeaders {
if user, ok := model.WhoisFromContext(r.In.Context()); ok {
// ok=true even for empty Whois{} stored by ProviderUserMiddleware
r.Out.Header.Set(consts.HeaderAuthToken, core.ProxyAuthToken()) // token sent to backend
}
}
// admin.go: management port trusts x-tsdproxy-id from localhost when token is valid
func ResolveWhois(r *http.Request) model.Whois {
if IsLocalhost(r.RemoteAddr) {
return model.Whois{
ID: r.Header.Get(consts.HeaderID), // attacker-controlled after stealing token
}
}
return model.Whois{}
}
Steps to reproduce
1. Deploy tsdproxy on a host (non-Docker) with a backend at http://localhost:3000.
2. Make a reques
Details
Original advisory: https://github.com/advisories/GHSA-g936-7jqj-mwv8
More from GitHub Security Advisories
- highGHSA-fpg8-7664-jc5q: melange: Incomplete package integrity verification allows data section substitution2026-07-10
- mediumGHSA-48rx-c7pg-q66r: Excon does not redact additional sensitive/risky headers when following redirects2026-07-10
- highGHSA-h4g2-xfmw-q2c9: Clauster: Non-loopback deployments can serve the dashboard unauthenticated when auth.enab…2026-07-10
- mediumGHSA-rqq5-2gf9-4w4q: Secure Headers: CSP directive injection via sandbox, plugin_types, and report_to when giv…2026-07-10
- criticalGHSA-56mp-4f3v-fgj2: SiYuan: Stored XSS to RCE via Unsanitized Attribute View Asset Cell Content2026-07-10