Project

General

Profile

Bug #11494

AI spotted security issue VirtualDesktopWebHandler.handleSsoReauth

Added by Sergey Ivanovskiy 2 months ago. Updated about 2 months ago.

Status:
New
Priority:
Normal
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
production:
No
env_name:
topics:

issue_8.txt Magnifier (5.53 KB) Sergey Ivanovskiy, 05/22/2026 11:11 AM

issue_9.txt Magnifier (2.04 KB) Sergey Ivanovskiy, 05/22/2026 03:56 PM

issue_10.txt Magnifier (3.45 KB) Sergey Ivanovskiy, 05/22/2026 03:58 PM

History

#1 Updated by Sergey Ivanovskiy 2 months ago

Please check if it is a real issue.

#2 Updated by Sergey Ivanovskiy about 2 months ago

New issue that can be fixed in this task too.

#3 Updated by Sergey Ivanovskiy about 2 months ago

I will delegate this issue to this task.

#4 Updated by Stefanel Pezamosca about 2 months ago

  • Assignee set to Stefanel Pezamosca

Thanks for reporting this, there are some good points here. I'll handle it.

#5 Updated by Hynek Cihlar about 2 months ago

Sergey, please don't add notes in the form of txt attachments. First it is hard to read through and second I don't think the attachments are included in the full text search index.

#6 Updated by Stefanel Pezamosca about 2 months ago

I'll post the contents here:
  • [MAJOR] functional SsoReauth.handleSsoReauth: postMessage contract has no nonce or session identifier — any frame on serverOrigin (e.g. compromised iframe, XSS) can fake {type:'sso-reauth-success'} and dismiss the overlay without an actual re-auth. Include a server-issued state/nonce that ties the message to the in-progress reauth.
    PROPOSED FIX:
    Have the server generate a cryptographic nonce when issuing MSG_SSO_REAUTH, embed it as the OIDC state on the reauthUrl and validate it in handleReauthCallback; emit the same nonce back to the opener inside the postMessage payload (and never use '*' as targetOrigin). On the client, capture the nonce from MSG_SSO_REAUTH, validate event.data.nonce === expectedNonce before treating any message as authoritative, and reject mismatches.
  • [MAJOR] functional SsoReauth.btnRelogin.onclick: After sso-reauth-failed the user is invited to click Re-login again, but the captured reauthUrl (sso_reauth.js:137) contains the same OIDC state parameter; OidcSsoAuthenticator.processReauthCallback at line 347 calls lookupAndRemoveReauthState(state) BEFORE the token exchange, consuming the state on the first /reauthcb hit. Any retry returns "Invalid or expired re-auth state". The client must request a fresh re-auth URL (or the server must keep the state until exchange succeeds).
    PROPOSED FIX:
    Move the lookupAndRemoveReauthState() call so it executes only on a successful token exchange. The state remains valid for the user's second Re-login attempt if the first OIDC exchange fails; on success the state is consumed exactly once. This is preferred over (a) and (b) because it requires no extra round trip or new message type and keeps the existing reauthUrl reusable until success.
  • [MAJOR] functional SsoReauth.handleSsoReauth: No re-entrancy guard. Two MSG_SSO_REAUTH messages in quick succession both await cleanupReauthUi(true) (idempotent via that.closed) and both reach the new p2j.ModalDialog('p2j-sso-reauth-dialog', ...) at sso_reauth.js:156. The second new Dialog({id: that.id}) at p2j.js:2013-2015 conflicts in the dijit registry.
    PROPOSED FIX:
    Add a module-scope inProgress Promise that serializes handleSsoReauth invocations. The second concurrent call awaits the first to complete before constructing its own dialog, eliminating the race window between cleanupReauthUi resolving and the new ModalDialog/dijit registration. The promise is cleared in a finally block so success and failure paths both release the lock.

Also available in: Atom PDF