Summary
In pkg/server/proxy/proxy.go:423, the ServiceAccount handler extracts clusterName from a JWT without signature verification and directly concatenates it into the URL path.
There is already a TODO comment in the code acknowledging this (TODO(#68)).
Risk
A crafted JWT payload with clusterName set to ../root or root:system could target arbitrary cluster paths. Since the admin transport is used, a successful traversal would hit kcp with admin credentials.
Code
// clusterName from UNVERIFIED JWT claim:
req.URL.Path = "/clusters/" + clusterName + req.URL.Path
// Transport: p.transport // admin transport
Recommendation
Validate clusterName against a strict format before use:
matched, _ := regexp.MatchString(`^[a-z0-9]+(?:[:-][a-z0-9]+)*$`, clusterName)
if !matched {
writeUnauthorized(w)
return
}
Summary
In
pkg/server/proxy/proxy.go:423, the ServiceAccount handler extractsclusterNamefrom a JWT without signature verification and directly concatenates it into the URL path.There is already a TODO comment in the code acknowledging this (
TODO(#68)).Risk
A crafted JWT payload with
clusterNameset to../rootorroot:systemcould target arbitrary cluster paths. Since the admin transport is used, a successful traversal would hit kcp with admin credentials.Code
Recommendation
Validate
clusterNameagainst a strict format before use: