LibreNMS SSRF-Driven Stored XSS via Oxidized API Response Fields
An admin can point LibreNMS's Oxidized integration at an attacker-controlled server, which returns HTML-injected JSON fields that LibreNMS renders unescaped on the device config tab, giving any…

The problem
LibreNMS fetches device metadata from the admin-configured oxidized.url endpoint and renders JSON fields (name, ip, model, author, commit message) directly into HTML inside includes/html/pages/device/showconfig.inc.php without calling htmlspecialchars().
Because the URL is admin-configurable and the output is stored in the page, any user who visits a device's showconfig tab after an admin points the URL at a malicious server will execute the injected script. The CVSS scope is Changed (C) because the XSS crosses from the admin's session context to all other users.
Proof of concept
A working proof-of-concept for this issue in librenms/librenms, with the exact payload below.
# 1. Admin sets oxidized.url to http://attacker.example.com/
# 2. Attacker server responds to /nodes.json with:
HTTP/1.1 200 OK
Content-Type: application/json
[{"name":"<img src=x onerror=alert('SSRF-XSS-oxidized')>","ip":"x","model":"x","group":""}]
# 3. Attacker server responds to /node/version?... with:
HTTP/1.1 200 OK
Content-Type: application/json
[{"oid":"abc","date":"2026-01-01","author":"<img src=x onerror=alert('author-xss')>","msg":"<img src=x onerror=alert('msg-xss')>"}]
# Result confirmed in advisory PoC:
# ...<strong>Node:</strong> <img src=x onerror="alert('SSRF-XSS-oxidized')">...The root cause is missing output encoding (CWE-79) on data fetched from an externally controlled HTTP endpoint (CWE-918). The PHP file concatenates $node_info['name'], $node_info['ip'], $node_info['model'], $author, and $msg directly into echo statements with no sanitization, so any HTML a malicious Oxidized server returns is rendered verbatim by the browser.
The patch wraps every field in htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before output, which neutralizes angle brackets and quotes and prevents the injected tags from being interpreted as HTML.
The fix
Upgrade to LibreNMS 26.7.0 or later. The patch adds htmlspecialchars(..., ENT_QUOTES, 'UTF-8') around every Oxidized-sourced field ($node_info['name'], $node_info['ip'], $node_info['model'], $author, $msg) in includes/html/pages/device/showconfig.inc.php.
If you cannot upgrade immediately, disable the Oxidized integration (oxidized.enabled = false) or restrict the oxidized.url setting to a trusted, network-isolated host.
Reported by murrant (LibreNMS maintainer, advisory publisher).
Related research
- high · 8.7CVE-2026-54347CVE-2026-54347: Froxlor Stored XSS in DNS TXT Record Leads to Admin Account Takeover
- high · 8.1CVE-2026-32257CVE-2026-32257: Winter CMS Stored XSS via Backend Brand Settings Custom Styles
- high · 7.2CVE-2026-69246CVE-2026-69246: Guzzle Noncanonical Host SSRF Bypass
- high · 7.7CVE-2026-59931CVE-2026-59931: PHPSpreadsheet SSRF Whitelist Bypass via HTTP Redirect in WEBSERVICE()