CVE-2026-116576: OS Command Injection via Unicode Quotation Marks in Node.js systeminformation
Vulnerability ID: CVE-2026-116576
CVSS Score: 7.8
Published: 2026-10-28
CVE-2026-116576 (GHSA-3f7j-7jwc-fxfj) is an OS Command Injection vulnerability (CWE-78) in the Node.js systeminformation library prior to version 5.33.16 on Microsoft Windows. The services() API function dynamically constructs a PowerShell Get-CimInstance command using caller-supplied service names passed through sanitizeShellString(). While the sanitizer strips standard ASCII quotation marks, it permits Unicode typographic quotation marks (U+2018 through U+201E). Because the Windows PowerShell tokenizer recognizes Unicode quotation marks as valid string literal delimiters, an attacker who controls the service name input can break out of the CIM filter string and execute arbitrary PowerShell commands within the security context of the Node.js process.
TL;DR
Prior to version 5.33.16, the systeminformation Node.js package fails to strip Unicode typographic quotation marks in sanitizeShellString() on Windows. Attackers who can pass input to services() or getDynamicData() can use Unicode quotes to break out of a PowerShell Get-CimInstance filter string and execute arbitrary OS commands.
⚠️ Exploit Status: POC
Technical Details
- Vulnerability Type: OS Command Injection (CWE-78)
- Affected Component: systeminformation (services() in lib/processes.js & sanitizeShellString() in lib/util.js)
- Target Platform: Microsoft Windows (Node.js runtime)
- CVSS v3.1 Score: 7.8 HIGH (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
- EPSS Score: 0.145% (3.76th Percentile)
- Root Cause: Incomplete quote sanitization allowing Unicode smart quotes (U+2018-U+201E) to break out of PowerShell Get-CimInstance filter strings
- Patched Version: 5.33.16
- CISA KEV Status: Not Listed
Affected Systems
- systeminformation (npm package) < 5.33.16 on Microsoft Windows
-
systeminformation: < 5.33.16 (Fixed in:
5.33.16)
Code Analysis
Commit: 5014c6d
utils() sanitizeShellString extended (windows)
diff --git a/lib/processes.js b/lib/processes.js
index 4758d10..ad741f2 100644
--- a/lib/processes.js
+++ b/lib/processes.js
@@ -377,22 +360,23 @@ function services(srv, callback) {
if (srvs[0] !== '*') {
wincommand += ' -Filter "';
srvs.forEach((srv) => {
- wincommand += `Name='${srv}' or `;
+ // whitelist: srv is inserted into a PowerShell string
+ wincommand += `Name='${srv.replace(/[^a-zA-Z0-9 _.\-@]/g, '')}' or `;
});
wincommand = `${wincommand.slice(0, -4)}"`;
}
wincommand += ' | select Name,Caption,Started,StartMode,ProcessId | fl';
util.powerShell(wincommand).then((stdout, error) => {
diff --git a/lib/util.js b/lib/util.js
index 72bc631..1f14ec0 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -749,6 +749,9 @@ function sanitizeShellString(str, strict) {
s[i] === "'" ||
s[i] === '`' ||
s[i] === '"' ||
+ // unicode quotes (U+2018-U+201E) and dashes (U+2013-U+2015) are treated as ' " - by PowerShell
+ (s[i] >= '‘' && s[i] <= '„') ||
+ (s[i] >= '–' && s[i] <= '―') ||
s[i].length > 1 ||
(strict && s[i] === '(') ||
(strict && s[i] === ')') ||
Mitigation Strategies
- Upgrade systeminformation to version 5.33.16 or later to apply strict character allowlisting in services() and Unicode quote stripping in sanitizeShellString().
- Enforce strict allowlist validation (e.g., /^[a-zA-Z0-9 _.-@]+$/) on all user-supplied service names prior to invoking systeminformation.services() or systeminformation.getDynamicData().
- Run Node.js applications under least-privilege Windows service accounts rather than Administrator or NT AUTHORITY\SYSTEM.
- Monitor child process execution of powershell.exe spawned by node.exe and enable PowerShell Script Block Logging (Event ID 4104) to detect command injection attempts.
Remediation Steps:
- Audit package.json and package-lock.json (or yarn.lock / pnpm-lock.yaml) for systeminformation versions prior to 5.33.16.
- Run 'npm install systeminformation@^5.33.16' to update the dependency to the patched release.
- Review application code paths that pass HTTP query parameters, request bodies, or IPC arguments to si.services() or si.getDynamicData() and implement strict input allowlisting.
- Redeploy the updated application and verify via dependency scanning that no transitive dependencies resolve to systeminformation < 5.33.16.
References
- GitHub Security Advisory GHSA-3f7j-7jwc-fxfj
- NVD - CVE-2026-116576 Detail
- CVE.org Record - CVE-2026-116576
- CVEListV5 JSON Record for CVE-2026-116576
- Fix Commit 5014c6d25cfce7363b937977327baa853cdba0bf - utils() sanitizeShellString extended (windows)
- systeminformation Release v5.33.16
- systeminformation GitHub Repository
Read the full report for CVE-2026-116576 on our website for more details including interactive diagrams and full exploit analysis.
Top comments (0)