(raw string)
| 165 | } |
| 166 | |
| 167 | func validateCLICallbackURL(raw string) (*url.URL, error) { |
| 168 | if raw == "" { |
| 169 | return nil, fmt.Errorf("cli callback URL required") |
| 170 | } |
| 171 | u, err := url.Parse(raw) |
| 172 | if err != nil { |
| 173 | return nil, fmt.Errorf("invalid cli callback URL: %w", err) |
| 174 | } |
| 175 | if u.Scheme != "http" { |
| 176 | return nil, fmt.Errorf("cli callback URL must use http") |
| 177 | } |
| 178 | if u.Host == "" { |
| 179 | return nil, fmt.Errorf("cli callback URL must include a host") |
| 180 | } |
| 181 | if u.User != nil { |
| 182 | return nil, fmt.Errorf("cli callback URL must not include user info") |
| 183 | } |
| 184 | host := u.Hostname() |
| 185 | if host == "" { |
| 186 | return nil, fmt.Errorf("cli callback URL must include a host") |
| 187 | } |
| 188 | if host != "localhost" { |
| 189 | ip := net.ParseIP(host) |
| 190 | if ip == nil || !ip.IsLoopback() { |
| 191 | return nil, fmt.Errorf("cli callback URL must use a loopback host") |
| 192 | } |
| 193 | } |
| 194 | return u, nil |
| 195 | } |
| 196 | |
| 197 | // OAuthState is encoded into the OAuth state parameter. It carries the CSRF |
| 198 | // nonce and, for CLI-initiated logins, the callback URL and CLI state token. |
no outgoing calls
no test coverage detected