fix: only trust the server's origin in the desktop login frame (#1624)

The desktop sign-in iframe accepted AUTH_SUCCESS and system browser requests from whatever page it had navigated to, and posted replies (including 2FA temp tokens) to any origin. Messages must now come from the server's origin and replies are posted to it.

The web UI also treated any framing page as the desktop app and posted the JWT to it. It now also requires the Termix-Desktop user agent.
This commit is contained in:
ZacharyZcR authored and GitHub committed 2026-10-14 08:12:53 +08:00
1 parent 13f7aa95a3
commit 8c3f816407
4 files changed
+112 -4

No files matched your search

+14 -4
View File
@@ -73,11 +73,21 @@ export function ElectronLoginForm({
);
// postMessage from server Auth.tsx after the backend has set the HttpOnly cookie.
// Uses '*' as target origin because the iframe may be cross-origin (e.g. remote Docker server).
// Only the server's own origin is trusted: the iframe can navigate away
// (identity provider, redirects), and those pages must not hand us a token,
// start a system browser login, or receive the replies.
useEffect(() => {
let serverOrigin: string;
try {
serverOrigin = new URL(serverUrl).origin;
} catch {
return;
}
const handleMessage = async (event: MessageEvent) => {
try {
if (event.source !== iframeRef.current?.contentWindow) return;
if (event.origin !== serverOrigin) return;
if (!event.data || typeof event.data !== "object") return;
const {
type,
@@ -115,7 +125,7 @@ export function ElectronLoginForm({
providerId,
...result,
},
"*",
serverOrigin,
);
};
const electronAPI = (
@@ -181,14 +191,14 @@ export function ElectronLoginForm({
success: false,
error,
},
"*",
serverOrigin,
);
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, [handleAuthSuccess, t]);
}, [handleAuthSuccess, serverUrl, t]);
useEffect(() => {
const iframe = iframeRef.current;