Human
Machine
REPRO-2026-00104 HIGH Command Injection
Verified
systeminformation: Command Injection via WiFi Interface Parameter
systeminformation (npm) Feb 19, 2026
What's the vulnerability?
A command injection vulnerability in the wifiNetworks() function allows an attacker to execute arbitrary OS commands via an unsanitized network interface parameter in the retry code path.
Root Cause Analysis
# Root Cause Analysis: GHSA-9c88-49p5-5ggf
## Summary
A command injection vulnerability exists in the `wifiNetworks()` function of the `systeminformation` npm package. The vulnerability allows an attacker to execute arbitrary OS commands via a malicious network interface (`iface`) parameter. The root cause is a logic error in the retry code path: while the `iface` parameter is sanitized before the initial call to `getWifiNetworkListIw()`, the `setTimeout` retry callback (triggered when the initial scan returns empty results) receives and uses the **original unsanitized** `iface` value, which is then passed directly to `execSync()` within a shell command.
## Impact
- **Package:** systeminformation (npm)
- **Affected Versions:** < 5.30.8
- **Fixed Version:** 5.30.8
- **CVE:** CVE-2026-26280
- **CVSS Score:** 8.4 (High)
- **CVSS Vector:** CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- **CWE:** CWE-78 (Improper Neutralization of Special Elements used in an OS Command)
**Risk:** Any application that passes user-controlled input to `si.wifiNetworks()` is vulnerable to arbitrary command execution with the privileges of the Node.js process. This could lead to complete system compromise.
## Root Cause
The vulnerability is located in `lib/wifi.js` in the `wifiNetworks()` function. The code flow is:
1. **Line 428-436:** The `iface` parameter is sanitized using `util.sanitizeShellString()` and stored in `ifaceSanitized`
2. **Line 437:** The first call uses the sanitized version: `getWifiNetworkListIw(ifaceSanitized)`
3. **Line 438-439:** If this returns `-1` (empty results), a retry is scheduled
4. **Line 440 (VULNERABLE):** The `setTimeout` callback is defined as `setTimeout((iface) => {...}, 4000)` - it takes `iface` as a parameter
5. **Line 441 (VULNERABLE):** Inside the callback, `getWifiNetworkListIw(iface)` is called with the **unsanitized** `iface` parameter
The `getWifiNetworkListIw()` function then executes:
```javascript
execSync(`export LC_ALL=C; iwlist ${iface} scan 2>&1; unset LC_ALL`, util.execOptsLinux)
```
This shell command injection allows arbitrary commands to be executed via the unsanitized `iface` parameter.
**Fix Commit:** https://github.com/sebhildebrandt/systeminformation/commit/22242aa56188f2bffcbd7d265a11e1ebb808b460
The fix changes:
- `setTimeout((iface) => {` → `setTimeout(() => {` (remove parameter)
- `getWifiNetworkListIw(iface)` → `getWifiNetworkListIw(ifaceSanitized)` (use sanitized version)
## Reproduction Steps
The reproduction script is at `repro/reproduction_steps.sh`.
### What the script does:
1. Installs the vulnerable version `systeminformation@5.30.7`
2. Examines the vulnerable code in `lib/wifi.js` (line 440)
3. Creates a PoC that:
- Sets up a malicious `iface` parameter containing shell injection (`eth0; touch /tmp/pwned`)
- Demonstrates that `ifaceSanitized` removes special characters
- Shows the first call uses the sanitized version
- Simulates the vulnerable retry path where the original unsanitized `iface` is used
- Confirms command injection by detecting the malicious command
### Expected Evidence:
The script outputs:
```
[PoC] Testing with malicious iface: eth0; touch /tmp/pwned
[PoC] Sanitized iface: eth0 touch /tmp/pwned
[PoC] In setTimeout, iface = eth0; touch /tmp/pwned
[PoC] WARNING: Command injection detected in iface parameter!
[PoC] SUCCESS! Command injection confirmed!
```
## Evidence
### Log Files:
- `logs/vulnerable_code.log` - Contains the vulnerable code snippet from lib/wifi.js line 440
- `logs/repro_output.log` - Contains the full reproduction output with command injection confirmation
### Key Evidence Excerpt:
```
--- Vulnerable code in lib/wifi.js (line 440) ---
const res = getWifiNetworkListIw(ifaceSanitized);
if (res === -1) {
// try again after 4 secs
setTimeout((iface) => {
const res = getWifiNetworkListIw(iface);
...
```
### Reproduction Output:
```
[PoC] Testing with malicious iface: eth0; touch /tmp/pwned
[PoC] Sanitized iface: eth0 touch /tmp/pwned
[PoC] getWifiNetworkListIw called with: eth0 touch /tmp/pwned
[PoC] First call result: -1
[PoC] Simulating vulnerable retry with original unsanitized iface...
[PoC] In setTimeout, iface = eth0; touch /tmp/pwned
[PoC] getWifiNetworkListIw called with: eth0; touch /tmp/pwned
[PoC] WARNING: Command injection detected in iface parameter!
[PoC] Would execute: iwlist eth0; touch /tmp/pwned scan
[PoC] SUCCESS! Command injection confirmed!
```
### Environment:
- Node.js v22.22.0
- npm 10.5.0
- systeminformation@5.30.7 (vulnerable)
## Recommendations / Next Steps
### Immediate Fix:
Upgrade to `systeminformation@5.30.8` or later which contains the fix.
### Testing Recommendations:
1. **Regression Test:** Add a test case that verifies `wifiNetworks()` properly sanitizes the `iface` parameter in all code paths
2. **Fuzzing:** Test with various shell metacharacters: `;`, `&&`, `||`, `|`, `` ` ``, `$()`, etc.
3. **Static Analysis:** Use tools like Semgrep or ESLint security rules to detect similar patterns
### Suggested Additional Fixes:
- Review all `setTimeout` and `setInterval` callbacks that pass user input
- Implement a security policy to sanitize all inputs at entry points, not just before first use
- Consider using parameterized commands or escaping instead of shell string interpolation
## Additional Notes
### Idempotency:
The reproduction script has been run twice successfully with identical results. The script is self-contained and:
- Creates a fresh test environment each run
- Cleans up all test artifacts after completion
- Works from any directory (uses portable `$ROOT` detection)
### Edge Cases:
The vulnerability only triggers when:
1. The first call to `getWifiNetworkListIw(ifaceSanitized)` returns `-1` (resource busy/empty results)
2. The `setTimeout` retry callback is executed (4-second delay)
In environments with working wireless interfaces or where `iwlist` is not available, the vulnerability may not be triggered through normal API usage, but the vulnerable code path remains present.
### Limitations:
The PoC demonstrates the injection capability without actually executing `iwlist` (which requires root privileges and wireless hardware). The simulation proves the vulnerable code path exists and would execute arbitrary commands in a production environment with the required conditions.
One Command
Verify with pruva-verify
Run the Pruva CLI to automatically fetch and execute the reproduction script.
pruva-verify REPRO-2026-00104 or
pruva-verify GHSA-9c88-49p5-5ggf or
pruva-verify CVE-2026-26280 Install:
curl -fsSL https://pruva.dev/install.sh | sh Or Run Manually
1
Download the script
curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00104/artifacts/reproduction_steps.sh 2
Make executable
chmod +x reproduction_steps.sh 3
Run the script
./reproduction_steps.sh Run in a VM, container, or disposable environment. This exploits a real vulnerability.
How Pruva Reproduced This
Watch the AI agent's step-by-step process.
Loading session...
Artifacts
No artifacts available