CVE-2026-63135: YOURLS Stored XSS via Crafted Referer Header in Statistics Chart
An unauthenticated attacker can poison a YOURLS short link's referrer log with a crafted HTTP Referer header, causing arbitrary JavaScript to execute in an administrator's browser when they view that…

The problem
YOURLS records the HTTP Referer header on every redirect and later displays aggregated referrer domains inside a Google Charts JavaScript block on the per-link stats page.
The function yourls_google_array_to_data_table() in includes/functions-infos.php concatenates those domain labels directly into an inline <script> as ['$label', ...] with no JavaScript-string escaping. yourls_sanitize_url_safe() removes some characters but deliberately allows ', [, ], ,, and parentheses, so a crafted hostname breaks out of the JS string context and injects arbitrary code.
The stored payload executes in the admin origin whenever an authenticated user opens the stats page, giving the attacker full same-origin access including CSRF token theft and privileged API calls.
Proof of concept
A working proof-of-concept for CVE-2026-63135 in yourls/yourls, with the exact payload below.
curl -H "Referer: http://x',1],['marker',alert(document.domain)],['z.tld/path" \
http://localhost/<existing-keyword>
# Then visit the stats page to trigger execution:
# http://localhost/<existing-keyword>+
# The crafted host survives sanitization and renders into the chart script as:
# var data = google.visualization.arrayToDataTable([
# ['x',1],['marker',alert(document.domain)],['z.tld',1]
# ]);The sink is yourls_google_array_to_data_table(), which builds a JS array literal by string-concatenating unsanitized labels: "['" . $label . "', " . $count . "]". A hostname containing ',1],['marker',alert(1)],['z.tld closes the current array element, injects a new element whose value is a function call, and reopens the array, all within valid JS syntax.
yourls_sanitize_url_safe() is URL-focused and intentionally keeps characters like single quotes and parentheses that are valid in URLs. Those same characters are JS string and expression metacharacters, so sanitization that is correct for URL storage is insufficient for JavaScript embedding.
The fix in PR #4107 (commit e1e93476) adds JS-string escaping (at minimum backslash-escaping single quotes and backslashes) to labels before they are concatenated into the chart script, closing the string-breakout vector. CWE-79: Improper Neutralization of Input During Web Page Generation.
The fix
Upgrade to YOURLS 1.10.4. The patch is in commit e1e93476655107e6caab34e52259eb1c91079ec7 (PR #4107). If you cannot upgrade immediately, disable public statistics pages (YOURLS_PRIVATE_INFOS should not be set to false) to limit exposure to authenticated users only, and audit any plugins that call yourls_stats_pie() or yourls_google_array_to_data_table() directly.
Reported by Thai Son Dinh, VinSOC Labs (R&D).
Related research
- high · 8.7CVE-2026-54347CVE-2026-54347: Froxlor Stored XSS in DNS TXT Record Leads to Admin Account Takeover
- high · 8.1LibreNMS SSRF-Driven Stored XSS via Oxidized API Response Fields
- high · 8.1CVE-2026-32257CVE-2026-32257: Winter CMS Stored XSS via Backend Brand Settings Custom Styles
- highCVE-2026-62944CVE-2026-62944: MantisBT Stored XSS via Attachment Filename in HTML Export