mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
A generic remote MCP connection lets the server it points at advertise its own authorization-server metadata, and `authorization_endpoint` was accepted as an arbitrary string: `startOAuth` built a `URL` from it and the board passed the result to `window.location.assign`. A hostile server could therefore advertise `javascript:`/`data:` to run script in the board's origin, `file:` to read a local path, or plain `http:`/a credential-bearing URL to downgrade or disguise where the operator was being sent. Parse every OAuth endpoint through one shared validator instead — discovered metadata, `WWW-Authenticate` hints, pasted/persisted config, and gallery defaults alike. It requires https (loopback http only under the existing local-development policy, plus this deployment's own origin, which is how the smoke-lab fixture is served), and rejects embedded credentials, fragments and malformed values. Discovery drops an unusable endpoint so a second advertised authorization server still gets a chance, and raises the refusal only if nothing safe was found — so an unsafe value is never persisted and never reported as a bare "does not advertise OAuth sign in". The token and registration endpoints go through the same gate, so a row written before this existed cannot send a code or client secret over plaintext. The board applies the same validator at the navigation boundary rather than trusting the response body, and — since a valid HTTPS page can still phish — names the authorization host on the redirect screen while keeping the "Unverified server" label. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>