security: harden OAuth discovery and token endpoints

Merged
JE
4mo ago
+2721-132

Harden OAuth discovery and token endpoints

(Threat: T1 malicious/compromised OAuth/discovery server.)

  • authorization_endpoint scheme validation (auth.go buildAuthURL): the endpoint comes from the server-controlled discovery doc and is later handed to OpenBrowser → xdg-open/open. Now required to be https (or http on loopback); a file:///--leading value is rejected before dispatch.
  • registration_endpoint scheme validation (registerBC3Client): the DCR path now validates the endpoint against the stricter isSecureEndpointURL whitelist (absolute URL with a non-empty host; https, or http on loopback), and re-validates every redirect hop with the same rule.
  • No-redirect OAuth client (appctx/context.go): CheckRedirect: ErrUseLastResponse. The exchange/refresh requests set GetBody, so Go would replay refresh_token/auth code to a redirect target; RFC 6749 token endpoints don't legitimately 3xx-redirect POSTs. Mirrors the SDK API client's redirect guard.

Tests

TestBuildAuthURL_RejectsUnsafeScheme (accepts https / http-loopback, rejects file://, foreign http://, javascript:, -flag).


Part 3/6 of the stacked security series. Base: security/02-output-ansi-sanitize.

šŸ“š Stack (merge bottom-up)

  1. #478 — reject foreign-host URLs in api (base main)
  2. #479 — strip ANSI/OSC escapes from output
  3. #480 — harden OAuth discovery / token endpoints
  4. #481 — close config trust-boundary gaps + completion gate
  5. #482 — tighten config-dir perms + plugin scope argv
  6. #483 — bump toolchain/x-net + CI gates

Each is independent except #482 depends on #481 (shared root.go). #478 can land first/alone.