KamoCRM

The meet-provider OAuth result page can no longer break out of its own script tag

FixMediaService
Shipped
September 23, 2026 at 10:03 AM UTC
Author
Kamo
Commit
617c224

MeetProviderController's GET /oauth/callback is sessionless and reflects the provider's error_description into an inline <script> block. The old jsString() only escaped backslash/quote/newline, so a value shaped like </script><script>...</script> ended the element early and ran attacker HTML on the public API gateway host (probed live and confirmed reflected verbatim, no auth required). jsString() now also escapes < > & / and the JS line terminators U+2028/U+2029 as \u escapes, because the HTML tokenizer looks for a bare </script while reading script content, before it has any notion of JS string quoting - keeping those bytes out of the output entirely is what stops it, not better JS quoting. The result page also now carries a per-response nonce on its <script> tag and a matching restrictive Content-Security-Policy header, as a second layer in case an escaper ever has a gap. postMessage still targets '*': this endpoint is the shared gateway host for every tenant, including orgs on their own custom domain, so there is no single opener origin to pin, and kamo-internal's own listener already treats delivery as best-effort for the same reason. Covered by **************** mutation-checked against the old escaping (reverting it turns the new </script>-boundary assertion red).

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing