Skip to content
Blog

npm · PyPI · office-converter

npm and PyPI: 6 Packages With 9.8 Shell Command Injection (office-converter, webp-converter, pypdftk…)

Six npm and PyPI packages (office-converter, webp-converter, pypdftk, doc-recog, whisper-node, transcribe2texts) hand file paths to a shell. All rated 9.8.

On October 14, 2026, NVD published six CVEs rated 9.8 in one go, all in npm and PyPI packages. Document, image and audio-transcription helpers — the kind of dependency you add without a second thought.

All six share one root cause: a caller-supplied file path is concatenated into a command string, then executed by a shell. If that path comes, directly or not, from a user — an uploaded file name, an API parameter — an attacker runs commands with the privileges of the Node.js or Python process.

PackageEcosystemCVENVD boundsOffending call
office-converternpmCVE-2020-37282≤ 1.0.2child_process.exec()
webp-converternpmCVE-2026-110635< 3.0.0 (fixed in 3.0.0)execFile with shell enabled
pypdftkPyPICVE-2026-110636≤ 0.5subprocess.Popen(..., shell=True)
doc-recognpmCVE-2026-110638≤ 1.1.6shell-based exec
whisper-nodenpmCVE-2026-110640≤ 1.1.1shelljs exec()
transcribe2textsnpmCVE-2026-110643≤ 1.0.6child_process.exec()

All of them: CVSS 3.1 9.8, vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, NVD published October 14, 2026, none in CISA KEV as of writing.


Why It Matters — and Why the 9.8 Depends on You

These packages wrap command-line tools (unoconv, cwebp, pdftk, pdftotext, whisper.cpp). The quick way to call them is to build a string and hand it to a shell. The catch: the shell interprets that string. Any special character in the file name becomes syntax.

The 9.8 score assumes the worst case: the path is controlled remotely, without authentication. In your application, it depends on the data flow:

  • Exposed: a service that receives an uploaded file and reuses its original name for conversion or transcription.
  • Less exposed: an internal script that only processes files you generate, with names you control.

When in doubt, assume you're exposed. A file name from outside is never trusted data.


office-converter — CVE-2020-37282

office-converter through 1.0.2 contains an OS command injection vulnerability [...] concatenated into an unoconv command run via child_process.exec()

The PDF and HTML generation functions take a file name that ends up in an unoconv command. NVD bounds it at 1.0.2 inclusive and names no fixed version. If you can't confirm a fix from the maintainer, replace the package or call unoconv yourself without a shell.

webp-converter — CVE-2026-110635

The helpers running the libwebp binaries use execFile… with the shell enabled, which defeats the point of execFile. Both file names and option strings are affected. NVD states the fix is in 3.0.0 — the only package in this batch with a published fixed version. Upgrade to 3.0.0 and check for API changes.

pypdftk — CVE-2026-110636

On the Python side: the form-filling and field-extraction functions build the pdftk command from input and output paths, then run it with shell=True. NVD bounds: ≤ 0.5, no fixed version published.

doc-recog — CVE-2026-110638

The document recognition and tagging functions pass the path to a pdftotext call that goes through a shell. NVD bounds: ≤ 1.1.6, no fixed version published.

whisper-node — CVE-2026-110640

The whisper.cpp wrapper builds its command line from the audio path and the language option, then runs it via shelljs. Note: even if you pin the path, a user-supplied language parameter is enough. NVD bounds: ≤ 1.1.1, no fixed version published.

transcribe2texts — CVE-2026-110643

Same pattern: the audio path is passed unescaped to child_process.exec(). NVD bounds: ≤ 1.0.6, no fixed version published.

A reminder for the whole table: these are NVD bounds. They mark the known vulnerable versions, not necessarily a fixed release to install. Check the maintainer's repository or advisory.


Detection

  • Dependency inventory, transitive ones included: npm ls office-converter webp-converter doc-recog whisper-node transcribe2texts and pip show pypdftk (or your SBOM).
  • Unexpected child processes of conversion workers: a sh spawning something other than the expected tool (curl, wget, an interpreter).
  • Outbound connections from conversion services that normally don't need any.
  • Odd file names in upload logs: unusual punctuation in names that should be plain.

Mitigation

  1. Upgrade webp-converter to 3.0.0. For the other five, check whether the maintainer has shipped a fix; otherwise remove or replace the dependency.
  2. Fix it on the calling side, whatever the package: in Node.js, execFile / spawn without the shell option, with arguments as an array; in Python, subprocess.run([...]) with a list and shell=False. Without a shell, a file name stays a file name.
  3. Never reuse an uploaded file's original name. Rename on receipt (random ID + validated extension) and store the original name separately in your database.
  4. Validate paths: resolve them, check they stay inside the intended working directory, reject anything outside a character allowlist.
  5. Validate options (language, format) against a closed list of values, never free text.
  6. Isolate conversion workers: dedicated unprivileged account, container with no outbound network, no secrets in the environment.

Why Continuous Monitoring of Your Dependencies Matters

None of these six packages is exotic: they're convenience wrappers added to save an hour. They then end up as transitive dependencies of projects that don't even know they're spawning a shell.

With cveo.tech, track your applications' sensitive libraries in your inventory and get alerted whenever a critical CVE hits them.

Every Monday

The week's critical CVEs, in your inbox

One email a week: the CVSS ≥ 9 vulnerabilities published in the last seven days, plus our latest analyses. Nothing else.

Double opt-in by email. Unsubscribe in one click, any time.

Watch your own assets

Free CVE search, asset inventory and email alerts.