This is a razor blade hidden in the revision log, and it only cuts when the right staff member opens the drawer
CVE-2026-30894 is a Joomla core cross-site scripting flaw in com_contenthistory, caused by missing output escaping when history data is rendered. The vendor advisory marks Joomla! CMS 3.0.0 through 5.4.5 and 6.0.0 through 6.1.0 as affected, with fixes in 5.4.6 and 6.1.1.
The vendor's *moderate* label is still a bit generous in enterprise reality. XSS can absolutely become full site compromise if it lands in a privileged admin browser, but this bug appears tied to a content-history workflow rather than anonymous front-end browsing, so the real story is *post-auth, role-limited, user-interaction-dependent abuse*; Joomla's own CVSS v4 view with PR:H/UI:P fits that reality better than the looser NVD v3 PR:N framing.
4 steps from start to impact.
Get content-editing foothold
- Authenticated Joomla access with permission to create or edit content that generates history entries
- A target site using vulnerable Joomla versions
- This is not an unauthenticated internet-to-RCE path
- Many enterprise Joomla sites have tightly limited publisher/editor roles
- SSO, MFA, and admin-network restrictions often gate backend access
Plant the XSS payload in revision data
com_contenthistory without proper escaping. The payload can be a simple <script> or event-handler style string, depending on the exact sink the patch corrected.- Ability to submit content or metadata that is preserved in content history
- The vulnerable rendering path must be reachable in the deployed workflow
- Some editors sanitize input before it ever reaches the sink
- Not every content field is necessarily rendered in history views
- A malformed payload may visibly break and get noticed by staff
Wait for a privileged user to open history
- A reviewer, editor, or administrator opens the affected history screen
- Victim browser executes active script content for the Joomla origin
- Requires user interaction, not just background page rendering
- Many admins rarely inspect revision history at all
- Browser protections and CSP can reduce payload reliability if well configured
Steal session context and pivot
- Victim account holds enough backend privilege to perform meaningful actions
- Session cookies or CSRF-protected workflows are reachable from the injected script
- Impact depends heavily on the victim's role
- Short session lifetimes, re-auth prompts, and step-up auth can blunt follow-on abuse
- EDR/browser controls may catch post-exploitation tooling on managed admin workstations
The supporting signals.
| In-the-wild status | No public exploitation evidence surfaced in the vendor advisory, NVD entry, or GitHub review. Upstream intel provided with this case says not KEV-listed. |
|---|---|
| PoC availability | No mature public PoC was found during review. For defenders, that matters less than usual because XSS payload creation is trivial once the vulnerable sink is understood. |
| EPSS | EPSS provided in the case data is 0.00005, which is floor-level and consistent with a narrow, workflow-dependent exploit path. |
| KEV status | Not listed per the case intel. No CISA catalog hit surfaced during review, and there is no sign this has crossed into 'drop everything' territory. |
| CVSS vector reality check | NVD shows CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N, but the Joomla CNA/NVD page also shows a Joomla CVSS v4 string with high privileges and passive user interaction. The v3 PR:N view likely overstates reachability for real deployments. |
| Affected versions | Vendor advisory and NVD align on 3.0.0-5.4.5 and 6.0.0-6.1.0 as affected. |
| Fixed versions | Upgrade to Joomla 5.4.6 or Joomla 6.1.1. No primary-source distro backport guidance surfaced in review. |
| Exposure/scanning data | No primary-source GreyNoise/Censys/Shodan telemetry specific to this CVE surfaced. Internet exposure is really about Joomla admin panels and editorial workflows, not a universally reachable anonymous endpoint. |
| Disclosure timeline | Reported to Joomla on 2026-04-01 and fixed/disclosed on 2026-05-26. |
| Reporter | Reported by Phan Phan Hai Long per the Joomla security advisory. |
noisgate verdict.
The decisive factor is attacker position: this appears to require a pre-existing authenticated foothold in Joomla's content workflow plus a privileged user opening the history view. That compounding friction sharply limits reachable population and makes this a post-initial-access privilege-pivot bug, not a broad external compromise path.
Why this verdict
- Requires a foothold first: the attacker generally needs authenticated ability to create or edit content that lands in
com_contenthistory, which implies prior credential theft, insider access, or another CMS compromise stage. - Requires the right victim and UI path: exploitation depends on a reviewer/admin actually opening the affected history component, so reachable population is far smaller than the product install base.
- Internet-wide blast radius is overstated: XSS impact can be serious, but only after the attacker crosses several narrowing gates; that is exactly the kind of friction that should drag a vendor MEDIUM down in enterprise patch triage.
Why not higher?
There is no sign of KEV status, active exploitation, wormability, or unauthenticated remote code execution. The path looks chained: authenticated content manipulation, then privileged user interaction, then session abuse. That is too much real-world friction to justify MEDIUM or HIGH urgency across a 10,000-host estate.
Why not lower?
It is still a core CMS bug in a widely deployed platform, and successful admin-origin XSS can translate into meaningful integrity impact, including administrative action abuse. In shared editorial environments or agencies with many backend users, the odds of the workflow being exercised are not zero, so this is not pure noise.
What to do — in priority order.
- Restrict
/administratorexposure — Put Joomla backend access behind VPN, IP allowlists, or an identity-aware proxy. For a LOW verdict there is no SLA beyond backlog hygiene, but this is worth doing on exposed sites because it shrinks the victim pool and makes the prerequisite authenticated foothold harder to obtain. - Trim editor and publisher roles — Review who can create or modify content that generates history entries, and remove stale or shared accounts. With no mitigation SLA for LOW, do this during normal access-review cadence, prioritizing internet-facing or multi-editor sites.
- Harden admin browser controls — Apply a strict admin-side CSP where feasible, use managed browsers, and block risky extension usage on administrator workstations. This won't guarantee prevention, but it raises exploit reliability friction for any XSS that does execute.
- Monitor high-risk admin actions — Alert on new super-user creation, extension installation, template edits, and major config changes shortly after content-history views. For LOW, fold this into standard CMS monitoring improvements rather than emergency change windows.
- A generic perimeter WAF is not a reliable answer here, because the vulnerable path is tied to authenticated backend rendering and normal application behavior.
- External attack-surface scanners will not meaningfully prioritize this; most won't authenticate, generate revision history, and then validate execution in the admin workflow.
- Focusing only on anonymous front-end hardening misses the actual risk, which is backend session abuse after a content authoring foothold.
Crowdsourced verification payload.
Run this on the Joomla web host against the site root, for example sudo bash check-joomla-cve-2026-30894.sh /var/www/html/joomla. It needs read access to the Joomla installation files only; root is not required unless file permissions force it.
#!/usr/bin/env bash
# check-joomla-cve-2026-30894.sh
# Detect whether a local Joomla installation is in the affected version ranges for CVE-2026-30894.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/runtime error
set -u
usage() {
echo "Usage: $0 /path/to/joomla-root"
}
if [ $# -ne 1 ]; then
usage
exit 3
fi
ROOT="$1"
XML_FILE="$ROOT/administrator/manifests/files/joomla.xml"
VER_FILE="$ROOT/libraries/src/Version.php"
VERSION=""
if [ -f "$XML_FILE" ]; then
VERSION=$(grep -Eo '<version>[^<]+' "$XML_FILE" 2>/dev/null | head -n1 | sed 's/<version>//')
fi
if [ -z "$VERSION" ] && [ -f "$VER_FILE" ]; then
SHORT=$(grep -E "public const SHORT_VERSION\s*=" "$VER_FILE" 2>/dev/null | head -n1 | sed -E "s/.*'([^']+)'.*/\1/")
if [ -n "$SHORT" ]; then
VERSION="$SHORT"
fi
fi
if [ -z "$VERSION" ]; then
echo "UNKNOWN - could not determine Joomla version from $XML_FILE or $VER_FILE"
exit 2
fi
# Normalize: keep only numeric dotted prefix
VERSION=$(echo "$VERSION" | sed -E 's/^([0-9]+(\.[0-9]+){0,2}).*/\1/')
ver_ge() {
# returns 0 if $1 >= $2
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$2" ]
}
ver_lt() {
# returns 0 if $1 < $2
[ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
# Affected ranges per vendor/NVD:
# 3.0.0 - 5.4.5
# 6.0.0 - 6.1.0
if ver_ge "$VERSION" "3.0.0" && ver_lt "$VERSION" "5.4.6"; then
echo "VULNERABLE - Joomla version $VERSION is in affected range 3.0.0-5.4.5"
exit 1
fi
if ver_ge "$VERSION" "6.0.0" && ver_lt "$VERSION" "6.1.1"; then
echo "VULNERABLE - Joomla version $VERSION is in affected range 6.0.0-6.1.0"
exit 1
fi
if ver_ge "$VERSION" "5.4.6" && ver_lt "$VERSION" "6.0.0"; then
echo "PATCHED - Joomla version $VERSION is at or above 5.4.6"
exit 0
fi
if ver_ge "$VERSION" "6.1.1"; then
echo "PATCHED - Joomla version $VERSION is at or above 6.1.1"
exit 0
fi
echo "UNKNOWN - Joomla version $VERSION is outside the published affected/fixed ranges reviewed for CVE-2026-30894"
exit 2
If you remember one thing.
5.4.6 or 6.1.1; for a LOW verdict there is no noisgate mitigation SLA and no noisgate remediation SLA — treat this as backlog hygiene. If you need a temporary control before patching, restrict /administrator access and review stale editor accounts during the same maintenance cycle.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.