GitHub Security Advisory: GHSA-5vv4-hvf7-2h46
Package: systeminformation (NPM)
Severity: HIGH (CVSS 8.8)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Vulnerable versions: <= 5.30.7
Patched in: 5.31.0

Summary: Command Injection via Unsanitized `locate` Output in `versions()` — systeminformation

Details:
# Command Injection via Unsanitized `locate` Output in `versions()` — systeminformation

**Package:** systeminformation (npm)  
**Tested Version:** 5.30.7  
**Affected Platform:** Linux  
**Author:** Sebastian Hildebrandt  
**Weekly Downloads:** ~5,000,000+  
**Repository:** https://github.com/sebhildebrandt/systeminformation  
**Severity:** Medium  
**CWE:** CWE-78 (OS Command Injection)  

---

### The Vulnerable Code Path

Inside the `versions()` function, when detecting the PostgreSQL version on Linux, the code does this:

```javascript
// lib/osinfo.js — lines 770-776

exec('locate bin/postgres', (error, stdout) => {
  if (!error) {
    const postgresqlBin = stdout.toString().split('\n').sort();
    if (postgresqlBin.length) {
      exec(postgresqlBin[postgresqlBin.length - 1] + ' -V', (error, stdout) => {
        // parses version string...
      });
    }
  }
});
```

Here's what happens step by step:

1. It runs `locate bin/postgres` to search the filesystem for PostgreSQL binaries
2. It splits the output by newline and sorts the results alphabetically
3. It takes the **last element** (highest alphabetically)
4. It concatenates that path directly into a new `exec()` call with `+ ' -V'`

**No `sanitizeShellString()`. No path validation. No `execFile()`. Raw string concatenation into `exec()`.**

The `locate` command reads from a system-wide database (`plocate.db` or `mlocate.db`) that indexes all filenames on the system. If any indexed filename contains shell metacharacters — specifically semicolons — those characters will be interpreted by the shell when passed to `exec()`.

---

## Exploitation

### Prerequisites

For this vulnerability to be exploitable, the following conditions must be met:

1. **Target system runs Linux** — the vulnerable code path is inside an `if (_linux)` block
2. **`locate` / `plocate` is installed** — common on Ubuntu, Debian, Fedora, RHEL
3. **PostgreSQL binary exists in the locate database** — so `locate bin/postgres` returns results (otherwise the code falls through to a safe `psql -V` fallback)
4. **The attacker can create files on the filesystem** — in any directory that gets indexed by `updatedb`
5. **The locate database gets updated** — `updatedb` runs daily via systemd timer (`plocate-updatedb.timer`) or cron on most distros

### Step 1 — Verify the Environment

On the target machine, confirm locate is available and running:

```
which locate
# /usr/bin/locate

systemctl list-timers | grep plocate
# plocate-updatedb.timer    plocate-updatedb.service
# (runs daily, typically around 1-2 AM)
```

Check who owns the locate database:

```
ls -la /var/lib/plocate/plocate.db
# -rw-r----- 1 root plocate 18851616 Feb 14 01:50 /var/lib/plocate/plocate.db
```

Database is root-owned and updated by root. Regular users cannot update it directly, but `updatedb` runs on a daily schedule and indexes all readable files.

### Step 2 — Craft the Malicious File Path

The key insight is that **Linux allows semicolons in filen