kubernetes/kops · error

url not valid for STS request

Error message

url not valid for STS request

What it means

The presigned STS URL comes from an untrusted token, so isValidV2 enforces a strict shape before the verifier will contact it: https scheme, host equal to the configured STS host, path "/", and exactly one Action=GetCallerIdentity query parameter. Any deviation — including an http:// URL that would leak the request in plaintext — triggers this error, preventing SSRF and downgrade attacks.

Source

Thrown at pkg/bootstrap/awsbootstrap/verifier.go:403

	if u.Query().Get("Action") != "GetCallerIdentity" {
		return false
	}
	if len(u.Query()["Action"]) != 1 {
		return false
	}

	return true
}

// getCallerIdentityV2 will request the presigned token URL, and decode the returned identity.
func (s *stsRequestValidator) getCallerIdentityV2(ctx context.Context, httpClient *http.Client, decoded *awsV2Token) (*GetCallerIdentityResponse, error) {
	reqURL, err := url.Parse(decoded.URL)
	if err != nil {
		return nil, fmt.Errorf("parsing STS request URL: %w", err)
	}

	if !s.isValidV2(reqURL) {
		return nil, fmt.Errorf("url not valid for STS request")
	}

	req := &http.Request{
		URL:    reqURL,
		Method: decoded.Method,
		Header: decoded.SignedHeader,
	}
	response, err := httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("sending STS request: %v", err)
	}
	if response != nil {
		defer response.Body.Close()
	}

	responseBody, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("reading STS response: %v", err)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Regenerate the presigned URL with the AWS SDK against the STS endpoint matching the verifier's configured stsRequestValidator.Host (same region), using https.
  2. Ensure the presign uses the standard SDK Presign (GetCallerIdentity, GET) rather than hand-rolled URL construction.
  3. Compare the URL host on the failing token with s.Host to confirm region/endpoint mismatch, then align client region config.
  4. If tokens are proxied, verify no component rewrites scheme, host, path, or duplicates the Action query parameter.

Example fix

// Client-side presign must target the verifier's STS host over https:
// before (hand-built, wrong region/scheme)
url := "http://sts.us-east-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15&..."
// after
req, _ := stsclient.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
presigned, _ := stsclient.PresignGetCallerIdentity(ctx, req,
  sts.WithPresignClient(presignClient)) // https, correct region, Action=GetCallerIdentity
Defensive patterns

Strategy: try-catch

Validate before calling

u, err := url.Parse(token.URL)
if err != nil { return err }
valid := u.Scheme == "https" &&
  u.Host == expectedSTSHost &&
  u.Path == "/" &&
  u.Query().Get("Action") == "GetCallerIdentity" &&
  len(u.Query()["Action"]) == 1
if !valid { return fmt.Errorf("presigned URL host/scheme/action mismatch: host=%s scheme=%s", u.Host, u.Scheme) }

Type guard

func isWellFormedPresignedSTSURL(raw, expectedHost string) bool {
  u, err := url.Parse(raw)
  if err != nil { return false }
  return u.Scheme == "https" && u.Host == expectedHost && u.Path == "/" &&
    u.Query().Get("Action") == "GetCallerIdentity" && len(u.Query()["Action"]) == 1
}

Try / catch

result, err := verifier.VerifyToken(ctx, token)
if err != nil && strings.Contains(err.Error(), "url not valid for STS request") {
  // client presigned against wrong region/endpoint or http; re-presign on the node
  return nil, fmt.Errorf("check node's AWS region config and STS endpoint; regenerate token: %w", err)
}

Prevention

When it happens

Trigger: getCallerIdentityV2 (via verifyTokenV2) parses the token's URL successfully but isValidV2 returns false: scheme != https, Host != s.Host, Path != "/", Action query param != GetCallerIdentity, or Action present more than once.

Common situations: Tokens presigned against a different regional STS endpoint than the verifier expects (s.Host mismatch); client built the URL with http instead of https; duplicated Action parameter after URL re-encoding; man-in-the-middle or malicious token; presigning with a tool that appends extra query params.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/55c1d301a14d8f46. Report an issue: GitHub.