
HumHub 1.18.4 / 1.18.4-pl1 – Stored Cross-Site Scripting in oEmbed confirmation
7,4
High
Detected by

Fluid Attacks AI SAST Scanner
Disclosed by
Miguel Gómez
Summary
Full name
HumHub 1.18.4 / 1.18.4-pl1 – Stored Cross-Site Scripting in oEmbed confirmation rendering through malformed provider URL
Code name
State
Public
Release date
Affected product
HumHub
Vendor
HumHub
Affected version(s)
1.18.4
Fixed version(s)
1.18.5
Vulnerability name
Stored Cross-Site Scripting
Vulnerability type
Remotely exploitable
Yes
CVSS v4.0 vector string
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N
CVSS v4.0 base score
7.4
Exploit available
Yes
CVE ID(s)
Description
HumHub Community Edition 1.18.4 and 1.18.4-pl1 contain a stored Cross-Site Scripting (XSS) vulnerability in the oEmbed confirmation rendering workflow.
A low-privilege authenticated Space member who can create posts can store a crafted rich-text oEmbed link in Post[message]. When another authenticated user views the post, HumHub treats a malformed URL containing youtube.com as a supported oEmbed URL, builds a local confirmation prompt from attacker-controlled URL text, and reconstructs injected <script> tags with the response's valid CSP nonce. The payload executes in the victim's HumHub browser session.
Vulnerability
Root cause
Source - low-privileged post creation
A user with the normal
CreatePostpermission can submit rich-text content to:PostController::actionPost()loads the request body into thePostmodel:Persistence and rich-text post-processing
After the post is saved,
Post::afterSave()calls:The oEmbed extension scans the stored Markdown-like link syntax and extracts the
oembed:extension ID.Permissive oEmbed provider recognition
The default YouTube provider pattern is:
This checks whether
youtube.comoryoutu.beoccurs anywhere in the supplied string. It does not require a validhttporhttpsURL, a canonical host, or a host boundary.As a result, the following malformed value is treated as a supported YouTube oEmbed URL:
Unsafe confirmation prompt construction
When oEmbed confirmation is required and the domain is not already trusted,
UrlOembed::getOEmbed()callsconfirmationContent($url).confirmationContent()derives a display prefix with:For the malformed payload,
parse_url()returns a scheme and path but no host, so$urlPrefixbecomes the complete attacker-controlled string, including<script>.The value is then inserted as raw tag content:
The URL-derived data is not HTML-encoded before it is included in the confirmation HTML.
CSP nonce bypass through script reconstruction
After the confirmation HTML is built,
UrlOembed::getOEmbed()searches the result for<script>tags:For each matched script, HumHub registers JavaScript that creates a new
<script>element, copies attributes, sets the script text, and appendsHtml::nonce()to the attributes. The attacker-controlled script is therefore recreated with a valid server-generated CSP nonce and executes in the victim's page.
Confirmed source-to-sink path
Authenticated attacker submits
Post[message]containing anoembed:rich-text link.The post is persisted by
PostController::actionPost().Post::afterSave()triggers rich-text post-processing.OembedExtensionrecords the malformed oEmbed extension ID becauseUrlOembed::hasOEmbedSupport()accepts it.When the post is rendered,
OembedExtension::parseOembeds()passes the same value toUrlOembed::getOEmbed().The default YouTube regex matches the substring
youtube.comin a malformed non-host URL.UrlOembed::confirmationContent()falls back to the raw URL as$urlPrefix.$urlPrefixis inserted into the confirmation prompt without output encoding.The resulting
<script>is detected by the oEmbed script handler and recreated withHtml::nonce().JavaScript executes in the authenticated victim's HumHub session.
Impact
An authenticated low-privileged Space member can store JavaScript in a post that executes when another authenticated user views the affected Space content.
Potential impact includes:
executing arbitrary JavaScript in the HumHub origin;
performing same-origin actions using the victim's authenticated browser session;
reading same-origin data exposed to the victim's session;
escalating practical impact when the victim is a global administrator or privileged Space user;
bypassing HumHub's nonce-based Content Security Policy for this injected script path.
PoC
Preconditions
HumHub Community Edition 1.18.4 or 1.18.4-pl1.
Default oEmbed providers are enabled.
The setting "Embedded content requires the user's consent to be loaded" remains enabled. This is the default behavior in
OEmbedSettingsForm.A regular Space member account with permission to create posts.
A victim account that can view the same Space.
Steps
Log in as a regular Space member.
Open a Space where the member can create posts.
Create a normal post and intercept the submit request.
Keep the original CSRF, container, and state parameters unchanged.
Replace only
Post[message]with:
Forward the request and let HumHub create the post.
Log in as another authenticated user who can access the same Space.
Open the malicious post.
Expected result:
HumHub renders an oEmbed confirmation block for the malformed URL.
The injected
<script>is reconstructed with a valid CSP nonce.The browser executes the script and shows the
Pwnedalert.
Non-dialog validation payload:
Expected result:
Evidence of Exploitation
Video of exploitation:
Static evidence:

Our security policy
We have reserved the ID CVE-2026-18526 to refer to this issue from now on.
System Information
Humhub
Version 1.18.4
Operating System: Any
References
GitHub Repository: https://github.com/humhub/humhub
Mitigation
An updated version of HumHub is available on the vendor page.
Credits
The vulnerability was discovered by Miguel Gomez from Fluid Attacks' Offensive Team using the AI SAST Scanner.
Timeline
Vulnerability discovered
Vendor contacted
Vendor replied
Vendor confirmed
Vulnerability patched
Public disclosure
Does your application use this vulnerable software?
During our free trial, our tools assess your application, identify vulnerabilities, and provide recommendations for their remediation.














