security: restrict OAuth callback postMessage targetOrigin to prevent session token leak#2464
Open
sebastiondev wants to merge 1 commit intoarc53:mainfrom
Open
security: restrict OAuth callback postMessage targetOrigin to prevent session token leak#2464sebastiondev wants to merge 1 commit intoarc53:mainfrom
sebastiondev wants to merge 1 commit intoarc53:mainfrom
Conversation
…ge (CWE-79) The OAuth callback-status page used wildcard "*" as the targetOrigin in window.opener.postMessage(), allowing any window that opened the OAuth popup to receive the session_token. An attacker could craft a page that opens the OAuth flow and intercepts the session token via postMessage. Changes: - Replace "*" targetOrigin with configurable FRONTEND_URL setting - Add FRONTEND_URL setting to Settings (defaults to http://localhost:5173) - Add origin validation on the frontend message event listener - Add regression tests for the postMessage targetOrigin fix
|
@sebastiondev is attempting to deploy a commit to the Arc53 Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The OAuth connector callback page (
ConnectorCallbackStatusinapplication/api/connector/routes.py) sends the authenticated user'ssession_tokenanduser_emailtowindow.openerviapostMessage(..., '*'). The wildcard target origin means any origin that opened the popup window will receive these credentials.application/api/connector/routes.py(ConnectorCallbackStatus.get)frontend/src/components/ConnectorAuth.tsx(handleAuthMessagedid not validateevent.origin)Data flow
window.open('https://docsgpt.example/api/connector/callback-status?...')(or initiates a connector OAuth flow that lands there).window.opener.postMessage({ session_token, user_email, ... }, '*').'*', the attacker's page receives the message and readsevent.data.session_token.The frontend listener also accepted messages from any origin, which compounds the risk in the other direction (attacker could spoof success/error events to a legitimate DocsGPT tab).
Fix
Two small, defensive changes:
routes.py+settings.py) — ReplacepostMessage(..., '*')withpostMessage(..., targetOrigin)wheretargetOriginis rendered from a newFRONTEND_URLsetting (defaulthttp://localhost:5173, matching the dev frontend). The value is rendered through the existingsafe_js_stringhelper so it stays HTML/JS-injection safe.ConnectorAuth.tsx) — InhandleAuthMessage, drop messages whoseevent.origindoes not match the configured API host (VITE_API_HOST). This guards the listener side against spoofed messages from other windows.Operators who deploy DocsGPT under a different frontend domain set
FRONTEND_URLaccordingly. The default keeps local development working out of the box.Testing
tests/test_cwe79_postmessage.pycovering:'*'as apostMessagetarget.targetOriginis the configuredFRONTEND_URL.safe_js_stringcontinues to escape the value (no HTML/JS injection via the setting).http://localhost:5173with the new default.session_tokenpayload.Adversarial review
Before submitting, we tried to disprove this. We checked whether DocsGPT's auth model or any framework-level header (CSP, COOP, etc.) already prevented the leak — it doesn't: there is no
Cross-Origin-Opener-Policyset on the callback response, and the only thing standing betweenwindow.openerand a third-party page is thetargetOriginargument itself, which was'*'. We also considered whether the popup is only ever opened from the trusted frontend in practice; it is not enforced —window.opencan be invoked from any page the victim visits, and the callback URL is reachable as long as the victim has a valid session. The fix closes the gap with a minimal change that preserves the existing dev-mode UX.cc @lewiswigmore