security(core): escape "<" in the res.expose script island (24.05) - #7950
Open
ar2rsawseen wants to merge 1 commit into
Open
security(core): escape "<" in the res.expose script island (24.05)#7950ar2rsawseen wants to merge 1 commit into
ar2rsawseen wants to merge 1 commit into
Conversation
…S via app name) Backport of #7949 to release.24.05. The dashboard serialises the exposed countlyGlobal object into an inline <script> block. The serialiser only neutralised the exact sequence "</script>", but the HTML tokeniser also ends a script element at "</script >", "</script/>" and other whitespace/slash spellings, so an application name containing one broke out of the script block. An app admin of a single app could store such a name; any global admin who then loaded the dashboard (which lists every app) executed the attacker's markup in their own session, escalating an app-admin account to global-admin control. Escape every "<" as < in both serialisation paths (string values and object keys). < parses back to "<", so every value read from the exposed object is unchanged; verified by an eval round-trip that reproduces the input object identically and matches the previous serialiser output. Also render the active-app name with .text() instead of .html() in countly.template.js, an independent DOM sink for the same value. Reported through the security bug bounty programme (received 2026-08-17). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Backport of #7949 to
release.24.05.frontend/express/libs/express-expose.jsserializes the exposedcountlyGlobalobject into an inline<script>block. It neutralized only the exact</script>sequence, but the HTML tokenizer also ends a script at</script >,</script/>and other whitespace/slash spellings, so an application name containing one broke out. Because a global admin's dashboard lists every app, an app admin of one app could store such a name and have it execute in any global admin's session — an app-admin-to-global-admin escalation. Medium under SECURITY.md.Fix (identical to #7949): escape every
<as<in both serialization paths — string values and object keys (escape_js_string).<parses back to<, so values read from the exposed object are unchanged. Also render the active-app name with.text()instead of.html()incountly.template.js(the only.html()sink fed by an app name).Verified on this branch: no raw
<survives for any breakout spelling in values or keys, and an eval round-trip reproduces the input object byte-for-byte and matches the previous serializer output (no dashboard-visible change).🤖 Generated with Claude Code