# REPRO-2026-00104: systeminformation: Command Injection via WiFi Interface Parameter ## Summary Status: published Severity: high Type: security Confidence: Unknown ## Identifiers REPRO ID: REPRO-2026-00104 GHSA: GHSA-9c88-49p5-5ggf CVE: CVE-2026-26280 ## Package Name: systeminformation Ecosystem: npm Affected: < 5.30.8 Fixed: 5.30.8 ## Root Cause # 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. ## Reproduction Details Reproduced: 2026-02-19T21:14:32.147Z Duration: 1177 seconds Tool calls: 107 Turns: 88 Handoffs: 2 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00104 pruva-verify GHSA-9c88-49p5-5ggf pruva-verify CVE-2026-26280 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00104&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00104/artifacts/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - GitHub Advisory: https://github.com/advisories/GHSA-9c88-49p5-5ggf - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-26280 - Source: https://github.com/advisories/GHSA-9c88-49p5-5ggf ## Artifacts - repro/rca_report.md (analysis, 6465 bytes) - repro/reproduction_steps.sh (reproduction_script, 5426 bytes) - bundle/ticket.md (ticket, 1954 bytes) - bundle/source.json (other, 4118 bytes) - bundle/ticket.json (other, 6540 bytes) - logs/variant_analysis.log (log, 1286 bytes) - logs/variant_fixed.log (log, 753 bytes) - logs/variant_vuln.log (log, 754 bytes) - logs/vulnerable_code.log (log, 520 bytes) - logs/repro_output.log (log, 637 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00104 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00104/artifacts/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00104 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev