fix(cloud/mcp): MCP approval page works in real browsers (referrer-policy same-origin; no-referrer made browsers send Origin: null, which the CSRF origin check refused)

This commit is contained in:
Neil
2026-11-13 03:38:39 -08:00
parent 34459d7565
commit 2a232cc3ab
2 changed files with 6 additions and 1 deletions
@@ -63,7 +63,10 @@ function securityHeaders(formAction: string): Record<string, string> {
// Clickjacking: never framed. form-action also covers the 302 to the client after submit.
'x-frame-options': 'DENY',
'content-security-policy': `default-src 'none'; style-src 'unsafe-inline'; img-src 'none'; script-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'self' ${formAction}`,
'referrer-policy': 'no-referrer',
// Not no-referrer: under no-referrer browsers send `Origin: null` on the form POST, which the
// same-origin check in oauth.ts refuses, so every real approval failed. same-origin still sends
// no referrer (and so none of the query) to any other origin.
'referrer-policy': 'same-origin',
'x-content-type-options': 'nosniff',
'cross-origin-opener-policy': 'same-origin'
}
@@ -425,6 +425,8 @@ describe('MCP authorization', () => {
const page = await h.send(new Request(`${ORIGIN}/oauth/authorize?${h.authorizeParams(client.client_id, challenge)}`))
expect(page.headers.get('x-frame-options')).toBe('DENY')
// Browsers only send a real Origin on the approval POST when the page's policy allows it (END-PASS: no-referrer broke every browser).
expect(page.headers.get('referrer-policy')).toBe('same-origin')
expect(page.headers.get('content-security-policy')).toContain("frame-ancestors 'none'")
expect(page.headers.get('content-security-policy')).toContain('form-action \'self\' http://127.0.0.1:33418')
expect(page.headers.get('set-cookie')).toMatch(/__Host-orca_mcp_csrf=\w+; Path=\/; Secure; HttpOnly; SameSite=Strict/)