parseTarget validates X-Lark-Proxy-Target and returns the host portion for HMAC input and allowlist lookup. The target must be "https:// " with no path, query, fragment, userinfo, or non-https scheme. Rejecting these shapes closes a token-leak channel: a compromised sandbox holding PROXY_KEY co
(target string)
| 245 | // otherwise request cleartext HTTP forwarding (or inject a path to a different |
| 246 | // endpoint than the allowlist entry implies). |
| 247 | func parseTarget(target string) (host string, err error) { |
| 248 | u, perr := url.Parse(target) |
| 249 | if perr != nil { |
| 250 | return "", fmt.Errorf("parse: %w", perr) |
| 251 | } |
| 252 | if u.Scheme != "https" { |
| 253 | return "", fmt.Errorf("scheme must be https, got %q", u.Scheme) |
| 254 | } |
| 255 | if u.Host == "" { |
| 256 | return "", fmt.Errorf("missing host") |
| 257 | } |
| 258 | if u.User != nil { |
| 259 | return "", fmt.Errorf("userinfo not allowed") |
| 260 | } |
| 261 | if u.Path != "" && u.Path != "/" { |
| 262 | return "", fmt.Errorf("path not allowed (got %q)", u.Path) |
| 263 | } |
| 264 | if u.RawQuery != "" { |
| 265 | return "", fmt.Errorf("query not allowed") |
| 266 | } |
| 267 | if u.Fragment != "" { |
| 268 | return "", fmt.Errorf("fragment not allowed") |
| 269 | } |
| 270 | return u.Host, nil |
| 271 | } |
no outgoing calls