Skip to content

CVE-2026-50289: Verified Repro With Script Download

CVE-2026-50289: systeminformation networkInterfaces Linux source-directive command injection

CVE-2026-50289 is verified against sebhildebrandt/systeminformation · github. Affected versions: <= 5.31.6. Fixed in 5.31.7. Vulnerability class: Command Injection. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00291.

REPRO-2026-00291 sebhildebrandt/systeminformation · github Command Injection Variant found Known vulnerability Jul 16, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.7
Confidence
HIGH
Reproduced in
14m 44s
Tool calls
126
Spend
$1.26
01 · Overview

What Is CVE-2026-50289?

CVE-2026-50289 is a high-severity OS command injection (CWE-78) in the sebhildebrandt/systeminformation npm library on Linux. Calling the public networkInterfaces() API can execute attacker-controlled shell commands as the Node.js process user. Pruva reproduced it (reproduction REPRO-2026-00291).

02 · Severity & CVSS

CVE-2026-50289 Severity & CVSS Score

CVE-2026-50289 is rated high severity, with a CVSS base score of 8.7 out of 10.

HIGH threat level
8.7 / 10 CVSS base
03 · Affected Versions

Affected sebhildebrandt/systeminformation Versions

sebhildebrandt/systeminformation · github versions <= 5.31.6 are affected.

How to Reproduce CVE-2026-50289

$ pruva-verify REPRO-2026-00291
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00291/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-50289

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

Shell-metacharacter-bearing path inside a Debian/Ubuntu 'source' directive line in a file reachable through /etc/network/interfaces source recursion (e.g. /etc/network/interfaces.d/*)

Attack chain
  1. public si.networkInterfaces()
  2. getLinuxDHCPNics()
  3. checkLinuxDCHPInterfaces('/etc/network/interfaces')
  4. recursive source traversal
  5. execSync(`cat ${file} 2> /dev/null | grep 'iface\|source'`) with unquoted ${file}
Runnable proof: reproduction_steps.sh
Captured evidence: vulnerable 5 31 6 apifixed 5 31 7 apiA fixed 5 31 7 apiB fixed 5 31 7 api
Variants tested

Negative variant/bypass search for CVE-2026-50289 (systeminformation networkInterfaces() source-directive command injection). The 5.31.7 fix replaces execSync(`cat ${file} | grep ...`) with fs.readFileSync, removing the shell from the source-directive recursion. No bypass on 5.31.7 or latest v5.31.17; the sibling ifac…

How the agent worked 465 events · 126 tool calls · 15 min
15 minDuration
126Tool calls
247Reasoning steps
465Events
3Dead-ends
Agent activity over 15 min
Policy
1
Support
12
Repro
78
Judge
263
Variant
106
Verify
1
0:0014:44

Root Cause and Exploit Chain for CVE-2026-50289

Versions: <5.31.7 (verified on 5.31.6 / commit da1cbf5).

On Linux, sebhildebrandt/systeminformation's public networkInterfaces() API reaches lib/network.jsgetLinuxDHCPNics()checkLinuxDCHPInterfaces('/etc/network/interfaces'). That helper reads the Debian/Ubuntu network-interface file, follows source directives recursively, and in versions <5.31.7 interpolates the parsed source path unquoted into a shell command executed via child_process.execSync():

function checkLinuxDCHPInterfaces(file) {
  let result = [];
  try {
    const cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
    const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
    ...
    if (line.toLowerCase().includes('source')) {
      const file = line.split(' ')[1];
      result = result.concat(checkLinuxDCHPInterfaces(file));   // recursive, unquoted
    }
  ...

Because ${file} is treated as shell text rather than a filename argument, shell metacharacters inside a source target execute arbitrary commands as the Node.js process user. The injected value originates from internal file content (a source line in a file reachable through /etc/network/interfaces source recursion, e.g. a file under /etc/network/interfaces.d/*), not from a direct API argument.

  • Package/component: systeminformation npm package, lib/network.js, checkLinuxDCHPInterfaces() (private helper reached by the public networkInterfaces() API and public aggregate callers getStaticData()/getAllData()).
  • Affected versions: <5.31.7 (verified on 5.31.6 / commit da1cbf5).
  • Risk level: High. Arbitrary command execution as the Node.js process user whenever an attacker can write or influence a file reached through the /etc/network/interfaces source recursion on a Debian/Ubuntu-style Linux host that calls the public network API.

Impact Parity

  • Disclosed/claimed maximum impact: Arbitrary command execution (code execution) via the public networkInterfaces() API on Linux.
  • Reproduced impact from this run: Arbitrary command execution confirmed — a harmless marker oracle file was created by the injected touch command only when the vulnerable 5.31.6 build processed the crafted source directive, and the call resolved normally (NETWORK_INTERFACES_RESOLVED, marker_exists=true).
  • Parity: full. The proof demonstrates attacker-controlled shell command execution (creation of an attacker-chosen file) through the public API on the vulnerable version, with the fixed version negative control showing no execution while the same benign source chain still parses.
  • Not demonstrated: A destructive payload was intentionally not used (safety constraint); only a harmless marker oracle was employed.

Root Cause

checkLinuxDCHPInterfaces(file) builds a shell command with an unquoted JS template-string interpolation of file:

const cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');

file is initially /etc/network/interfaces but, on each source directive line, the code extracts line.split(' ')[1] and recurses into checkLinuxDCHPInterfaces(file) with that raw, attacker-influenced value. Since the value is spliced into a shell string (not passed as an argument to execFileSync/readFileSync), any shell metacharacters in the source target are interpreted by /bin/sh. A source line such as:

source /tmp/pruva_inj_nonexist;touch<TAB>/tmp/pruva_cve_2026_50289_marker

is split by JS on the single space into file = "/tmp/pruva_inj_nonexist;touch\t/tmp/pruva_cve_2026_50289_marker" (the literal TAB survives because split(' ') only splits on the space character). The shell then parses cat /tmp/pruva_inj_nonexist;touch\t/tmp/marker 2> /dev/null | grep ... as two commands separated by ;, executing touch /tmp/marker (TAB is shell whitespace), creating the marker file.

Fix commit: bbfddde48672d0ee124fefdb3cb4442fd9dd4f03 (https://github.com/sebhildebrandt/systeminformation/commit/bbfddde48672d0ee124fefdb3cb4442fd9dd4f03) replaced execSync('cat ... | grep ...') with fs.readFileSync(file, { encoding: 'utf8' }) plus an in-JS .filter((l) => /iface|source/.test(l)), eliminating the shell entirely while preserving source-directive recursion.

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh (self-contained, idempotent).
  2. What it does:
    • Reuses the prepared project-cache repo (or clones sebhildebrandt/systeminformation when no cache exists).
    • Checks out the vulnerable release v5.31.6 (da1cbf5, parent of the fix) and the fixed release 5.31.7 (bbfddde).
    • Crafts a controlled /etc/network/interfaces containing a benign source directive (functional control pointing to a real DHCP iface config) and a malicious source directive whose target embeds ;touch<TAB> followed by a harmless marker path under /tmp.
    • Invokes only the public si.networkInterfaces(true) API for each build (no private helper is called directly).
    • Observes a harmless marker oracle file: created on 5.31.6, absent on 5.31.7.
    • Restores the original /etc/network/interfaces.
  3. Expected evidence:
    • logs/vulnerable_5_31_6_api.logNETWORK_INTERFACES_RESOLVED, marker_exists=true.
    • logs/fixed_5_31_7_api.logNETWORK_INTERFACES_RESOLVED, marker_exists=false.
    • logs/reproduction_steps.logVERDICT: CONFIRMED.
    • repro/runtime_manifest.jsontarget_path_reached=true, confirmed=true.

Evidence

  • Log files:

    • bundle/logs/reproduction_steps.log — full run transcript.
    • bundle/logs/vulnerable_5_31_6_api.log — vulnerable API output.
    • bundle/logs/fixed_5_31_7_api.log — fixed API output (negative control).
    • bundle/logs/interfaces.backup — original /etc/network/interfaces backup.
  • Key excerpts:

    Vulnerable (5.31.6):

    NETWORK_INTERFACES_RESOLVED
    marker_exists=true
    iface_count=2
    

    Fixed (5.31.7, same crafted source chain):

    NETWORK_INTERFACES_RESOLVED
    marker_exists=false
    iface_count=2
    

    Summary:

    vulnerable 5.31.6 marker created : true
    fixed     5.31.7 marker created : false
    VERDICT: CONFIRMED - command injection via public networkInterfaces() on 5.31.6; absent on fixed 5.31.7
    
  • Environment: Linux, Node v24.18.0, systeminformation built from source at commits da1cbf5 (v5.31.6) and bbfddde (5.31.7). No sanitizers; the marker oracle is a real filesystem side effect of an attacker-controlled shell command.

Recommendations / Next Steps

  • Upgrade: Update to systeminformation >= 5.31.7. The fix removes the shell entirely by using fs.readFileSync.
  • Defense in depth: For any remaining execSync/exec call sites in the package that interpolate file-system-derived values, switch to execFileSync/readFileSync with arguments passed as array elements, or validate paths against an allow-list.
  • Testing: Add a regression test that places a source directive with shell metacharacters in a controlled interfaces file and asserts no shell side effect occurs, while a benign source chain still parses.

Additional Notes

  • Idempotency: The script was run twice consecutively; both runs produced confirmed=true with identical evidence (vulnerable marker=true, fixed marker=false). The script backs up and restores the original /etc/network/interfaces on every run.
  • Safety: Only a harmless marker oracle (touch of an empty file under /tmp) was used; no destructive payload. The private checkLinuxDCHPInterfaces() helper was never invoked directly — only the public networkInterfaces() API was called.
  • Scope: The claim surface is library_api (function_call), matching the accepted claim contract. The proof exercises the real public API end-to-end on a real Linux runtime with the real package source; the fixed-version negative control confirms the patch blocks the injection while preserving benign source parsing.

Variant Analysis & Alternative Triggers for CVE-2026-50289

Versions: versions (as tested): vulnerable on v5.31.6

No distinct variant or bypass was found. The fix shipped in 5.31.7 (commit bbfddde) is complete and surgical: it replaced the only attacker-controlled-file→shell sink in the networkInterfaces() DHCP path — execSync(cat ${file} 2> /dev/null | grep 'iface\|source') inside checkLinuxDCHPInterfaces() — with fs.readFileSync(file, { encoding: 'utf8' }) plus an in-JS .filter((l) => /iface|source/.test(l)). Because readFileSync invokes no shell, shell metacharacters in a source-directive target are inert on the fixed and latest (5.31.17) releases. The only sibling data path an attacker can influence via /etc/network/interfaces.d/* — the iface-directive interface name — never reaches a shell command (it flows only to result.push(parts[1]) and later DHCPNics.indexOf(iface)), so it is not a variant of the same root cause. A bounded three-candidate search was executed and produced a negative result.

Fix Coverage / Assumptions

What the fix changes (lib/network.js, checkLinuxDCHPInterfaces(file)):

-    const cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
-    const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
+    const content = readFileSync(file, { encoding: 'utf8' });
+    const lines = content.split('\n').filter((l) => /iface|source/.test(l));

plus const readFileSync = require('fs').readFileSync; added to the imports.

Invariant the fix relies on: the source-directive recursion (result = result.concat(checkLinuxDCHPInterfaces(file)) where file = line.split(' ')[1]) now reads the next file with readFileSync instead of a shell cat. There is no shell anywhere in the recursion, so no interpolation of file-derived content into a command string can occur.

Code paths explicitly covered: every call that reaches checkLinuxDCHPInterfaces('/etc/network/interfaces') — i.e. the public networkInterfaces() API and the public aggregate callers getStaticData() / getAllData() that invoke it on Linux via getLinuxDHCPNics().

What the fix does NOT cover (examined, ruled out):

  • The iface-directive interface name (parts[1]) is parsed from the same attacker-writable files but is only pushed onto the DHCP nic list and later compared with DHCPNics.indexOf(iface) — it is never interpolated into a shell command, so it is not an uncovered variant sink.
  • Other execSync/exec sites in lib/network.js (e.g. the cat /sys/class/net/${ifaceSanitized}/... block at lines ~943-967) consume interface names from os.networkInterfaces() (system-controlled) and pass them through util.sanitizeString(); they do not consume attacker-writable file content and do not share this CVE's trust boundary.

Variant / Alternate Trigger

Three materially distinct candidate angles were tested (see bundle/vuln_variant/reproduction_steps.sh):

  • Candidate A — iface-directive NAME injection (sibling data path). Entry point: public si.networkInterfaces(true). A controlled /etc/network/interfaces contains an iface pruvaA;touch<TAB><marker> inet dhcp line, exercising the other directive type an attacker can write into the source-recursion tree. Tested on vulnerable 5.31.6 and fixed 5.31.7. Result: marker not created on either version — the parsed interface name never reaches execSync. Not a variant.

  • Candidate B — source-directive BYPASS on fixed/latest. Entry point: public si.networkInterfaces(true). A controlled /etc/network/interfaces contains source targets with three different shell-injection styles — ;touch<TAB>, $(touch<TAB>), and `touch<TAB>` — each pointing at its own harmless marker oracle. Tested on fixed 5.31.7 and latest 5.31.17. Result: none of the three markers were created on either version — readFileSync invokes no shell, so all metacharacters are inert. No bypass.

  • Candidate C — baseline sanity (original ;touch<TAB> source injection). Re-run on vulnerable 5.31.6 to prove the harness and sink still fire. Result: marker created (C_vuln marker=true), confirming the test rig is sound and the sink is reachable on the vulnerable version only.

Exact entry point for all candidates: the public si.networkInterfaces() library API (no private helper is called directly). Code path: networkInterfaces()getLinuxDHCPNics()checkLinuxDCHPInterfaces('/etc/network/interfaces') → recursive source-directive traversal (lib/network.js lines ~549-566).

  • Package/component: systeminformation, lib/network.js, checkLinuxDCHPInterfaces() (private helper reached by the public networkInterfaces() API and aggregate callers).
  • Affected versions (as tested): vulnerable on v5.31.6 (da1cbf5); fixed on 5.31.7 (bbfddde); also verified fixed on latest v5.31.17 (9e79988).
  • Risk level: the original CVE is High (arbitrary command execution as the Node.js process user). No additional variant/bypass risk was identified — the fix closes the sink completely.

Impact Parity

  • Disclosed/claimed maximum impact (parent CVE): arbitrary command execution as the Node.js process user via shell metacharacters in a source-directive target reachable through /etc/network/interfaces source recursion.
  • Reproduced impact from this variant run: no variant/bypass reproduced. The baseline (Candidate C) reproduced the original command injection on 5.31.6 only; all candidate variants were inert on the fixed and latest releases.
  • Parity: none — no distinct variant impact was demonstrated because no distinct variant exists.
  • Not demonstrated: N/A (negative result; no new code-execution path was found).

Root Cause

The original root cause was unquoted interpolation of an attacker-controlled-from-file path into a shell command: checkLinuxDCHPInterfaces() built cat ${file} | grep 'iface|source' and ran it via execSync, where ${file} came from line.split(' ')[1] of a source directive inside a file reachable through /etc/network/interfaces source recursion (e.g. /etc/network/interfaces.d/*). Shell metacharacters in that token were interpreted by /bin/sh.

The fix (commit bbfddde) eliminates the shell from this path entirely by reading the file with fs.readFileSync and filtering lines in JavaScript. The source-directive recursion is preserved, but it now recurses through readFileSync, which cannot execute commands. There is no remaining code path in the networkInterfaces() DHCP discovery flow that interpolates file-derived content into a shell command, so the same underlying bug cannot be reached from a different entry point or via different metacharacter encodings. The iface-directive name — the only other attacker-influenceable token parsed from the same files — was confirmed by test not to reach any shell sink.

Reproduction Steps

  1. Script: bundle/vuln_variant/reproduction_steps.sh (self-contained, idempotent).
  2. What it does:
    • Reuses the prepared project-cache repo (or clones sebhildebrandt/systeminformation when no cache exists).
    • Checks out the vulnerable release v5.31.6 (da1cbf5), the fixed release 5.31.7 (bbfddde), and the latest release v5.31.17.
    • For each candidate, crafts a controlled /etc/network/interfaces (plus a benign DHCP config under /etc/network/interfaces.d/), invokes only the public si.networkInterfaces(true) API, and observes distinct harmless marker oracles under /tmp.
    • Restores /etc/network/interfaces and restores the repo to bbfddde (the state the repro stage left it in).
  3. Expected evidence:
    • C_vuln marker = true (baseline sink fires on vulnerable).
    • A_vuln / A_fixed markers = false (iface-name path does not reach a shell).
    • B_fixed / B_latest markers (all three styles) = false (no bypass on fixed or latest).

Evidence

  • bundle/logs/vuln_variant_reproduction.log — full annotated run log.
  • bundle/logs/C_vuln_5_31_6_api.log — baseline API output on 5.31.6 (marker=true).
  • bundle/logs/A_vuln_5_31_6_api.log, bundle/logs/A_fixed_5_31_7_api.log — iface-name candidate (marker=false).
  • bundle/logs/B_fixed_5_31_7_api.log, bundle/logs/B_latest_5_31_17_api.log — source-bypass candidate (marker=false for ;, $(), and backtick styles).
  • bundle/logs/vuln_variant_interfaces.backup — original /etc/network/interfaces backup.

Key excerpt (second idempotent run):

C_vuln:/tmp/pruva_variant_markerC=true
A_vuln:/tmp/pruva_variant_markerA=false
A_fixed:/tmp/pruva_variant_markerA=false
B_fixed: ...markerB1=false ...markerB2=false ...markerB3=false
B_latest: ...markerB1=false ...markerB2=false ...markerB3=false
VERDICT: NO VARIANT/BYPASS - fix covers the source-directive sink; iface-name
data path does not reach a shell

Environment: Linux; Node.js; systeminformation built from source at commits da1cbf5 (v5.31.6), bbfddde (5.31.7), and 9e79988 (v5.31.17).

Recommendations / Next Steps

  • No gap to close. The fix is complete for the command-injection root cause. The Coding stage does not need to extend the patch for this CVE.
  • Defense-in-depth (optional, already partially present): the project already routes most shell-interpolated interface names through util.sanitizeString(). Maintainers may consider auditing the remaining execSync/exec template-literal sites in lib/network.js and lib/wifi.js to ensure every interpolated value is either system-controlled or sanitized, as a general hardening measure — but none of those constitute a bypass of this specific fix.
  • Recursion note: checkLinuxDCHPInterfaces still recurses on source-directive targets with no depth limit. This is a benign resource-use concern (unbounded recursion / file reads), not a command injection, and is out of scope for this CVE.

Additional Notes

  • Idempotency: the script was run twice; both runs completed cleanly with identical results (exit 1, no variant). No crashes.
  • Repo state preserved: the cache repo was restored to bbfddde (the commit the repro stage left it on) at the end of every run.
  • Trust boundary / threat model: the project's SECURITY.md treats security bugs as in-scope and commits to auditing for similar problems. The attacker preconditions (Linux; attacker can write a file reached through /etc/network/interfaces source recursion) match the parent CVE. The variant search stayed within that trust boundary and found no additional reachable sink.
  • Negative-result scope: fewer than 3 distinct bypass candidates exist because there is exactly one attacker-controlled-file→shell sink in the networkInterfaces() DHCP flow, and the fix removes the shell from it. Candidate A is a genuinely different data path (the iface directive) that was tested and ruled out; Candidate B is a genuinely different encoding set tested against the fixed code; Candidate C is the baseline control. Further attempts would re-exercise the same sink/data path and would not constitute materially distinct variants.

CVE-2026-50289 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support · claim contract · reproduction · judge · variant analysis

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:000:43
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-50289 · REPRO-20
0:03
0:04
0:05
web search
0:07
0:08
0:17
0:17
extract_facts
no facts extracted
0:18
0:18
supportclaim_contract
0:19
0:19
0:19
0:19
0:20
0:20
0:20
0:22
0:22
$ls -la /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243/ 2>/dev/null; echo "---repo---"; ls -la /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243/repo/ 2>/dev/null
{"cwd":"/data/pruva/runs/871f48bd-5e2c-49d2-b789-559e145055b3","duration_ms":7,"exit_code":2,"stderr":"","stdout":"total 0\ndrwxr-xr-x 1 vscode vscode   24 Jul 16 08:10 .\ndrwxr-xr-x 1 vscode vscode 7388 Jul 16 08:10 ..\ndrwxr-xr-x 1 vscode vscode    0 Jul 16 08:10 repo-mirrors\n---repo---\n","success":false,"timeout_secs":120}
0:22
error

Unknown error

0:23
0:26
0:27
$cd /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243 && git clone --quiet https://github.com/sebhildebrandt/systeminformation.git repo 2>&1 | tail -5; echo "EXIT=$?"; cd repo && git log --oneline -3 bbfddde48672d0ee124fefdb3cb4442fd9dd4f03 2>&1 | head
1.0s
EXIT=0
bbfddde networkInterfaces() fix unsanitized command (linux)
da1cbf5 5.31.6
87dbb60 fix: smaller issues
0:28
$cd /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243/repo && git checkout --quiet da1cbf5 2>&1; echo "vuln checkout EXIT=$?"; sed -n '530,640p' lib/network.js
{"cwd":"/data/pruva/runs/871f48bd-5e2c-49d2-b789-559e145055b3","duration_ms":14,"exit_code":0,"stderr":"","stdout":"vuln checkout EXIT=0\n}\n\nfunction getLinuxIfaceConnectionName(interfaceName) {\n  try {\n    const output = execFileSync('nmcli', ['device', 'status'], { ...util.execOptsLinux, stdio: ['ignore', 'pipe', 'ignore'] }).toString();\n    const result = util.grep(output, interfaceName);\n\n    const resultFormat = result.replace(/\\s+/g, ' ').trim();\n    const connectionNameLines = resultFormat.split(' ').slice(3);\n    const connectionName = connectionNameLines.join(' ');\n    const connectionNameSanitized = util.sanitizeString(connectionName, false);\n\n    return connectionNameSanitized !== '--' ? connectionNameSanitized : '';\n  } catch {\n    return '';\n  }\n}\n\nfunction checkLinuxDCHPInterfaces(file) {\n  let result = [];\n  try {\n    const cmd = `cat ${file} 2> /dev/null | grep 'iface\\\\|source'`;\n    const lines = execSync(cmd, util.execOptsLinux).toString().split('\\n');\n\n    lines.forEach((line) => {\n      const parts = line.replace(/\\s+/g, ' ').trim().split(' ');\n      if (parts.length >= 4) {\n        if (line.toLowerCase().indexOf(' inet ') >= 0 &&… [truncated]
0:42
0:42
$cd /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243/repo && git checkout --quiet bbfddde48672d0ee124fefdb3cb4442fd9dd4f03 2>&1; echo "fixed EXIT=$?"; sed -n '549,560p' lib/network.js; echo "---pkg main---"; grep -E '"main"|"name"|"version"' package.json
fixed EXIT=0
function checkLinuxDCHPInterfaces(file) {
  let result = [];
  try {
    const content = readFileSync(file, { encoding: 'utf8' });
    const lines = content.split('\n').filter((l) => /iface|source/.test(l));

    lines.forEach((line) => {
0:43
0:43
$cd /data/pruva/project-cache/ebe61b2a-f601-4416-916e-129c2338e243/repo && sed -n '549,575p' lib/network.js
function checkLinuxDCHPInterfaces(file) {
  let result = [];
  try {
    const content = readFileSync(file, { encoding: 'utf8' });
    const lines = content.split('\n').filter((l) => /iface|source/.test(l));

    lines.forEach((line) => {
      const parts = line.replace(/\s+/g, ' ').trim().split(' ');
08 · How to Fix

How to Fix CVE-2026-50289

Upgrade sebhildebrandt/systeminformation · github to 5.31.7 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-50289 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-50289

What has to be true to exploit CVE-2026-50289?

An attacker needs to influence the contents of /etc/network/interfaces (or a file it 'source's) so a source directive contains shell metacharacters, and then have the application call networkInterfaces() on Linux. Pruva verified command execution as the Node process user against systeminformation <= 5.31.6 with high confidence.

Which versions of systeminformation are affected by CVE-2026-50289, and where is it fixed?

sebhildebrandt/systeminformation versions <= 5.31.6 are affected; the issue is fixed in 5.31.7, which stops interpolating the unquoted source path into a shell command.

How severe is CVE-2026-50289?

It is rated high severity: reachable through a public, commonly used API (networkInterfaces()) and resulting in arbitrary OS command execution as the Node.js process user on Linux.

How can I reproduce CVE-2026-50289?

Download the verified script from this page and run it in an isolated Linux container against systeminformation <= 5.31.6. It plants a crafted source directive and calls networkInterfaces(), showing the injected command run — then confirms 5.31.7 no longer executes it.
11 · References

References for CVE-2026-50289

Authoritative sources for CVE-2026-50289 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.