---
id: "MAL-2026-17710"
kind: "package"
aliases: ["MAL-2026-17710"]
title: "Malicious code in pxnpm (npm)"
severity: "critical"
cvss: null
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "pxnpm", "fixed": [], "affected": "= 7.0.0-beta.6; = 7.0.0-beta.8; = 7.0.0; = 7.0.1; = 7.0.2", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["malicious", "package"]
not_affected_if: []
published_at: "2026-10-09T13:32:13+00:00"
first_seen_at: "2026-10-29T14:24:37+00:00"
updated_at: "2026-10-29T14:25:47+00:00"
sources: [{"source": "osv-malicious", "url": "https://osv.dev/vulnerability/MAL-2026-17710", "first_seen_at": "2026-10-29T14:24:37+00:00"}]
---

# Malicious code in pxnpm (npm)

## Affected

- npm:pxnpm affected = 7.0.0-beta.6; = 7.0.0-beta.8; = 7.0.0; = 7.0.1; = 7.0.2 fixed ?

## Timeline

- 2026-10-29T14:24:37+00:00 osv-malicious https://osv.dev/vulnerability/MAL-2026-17710

## From the sources

pxnpm 7.0.0-beta.6, 7.0.0-beta.8 and 7.0.0 (published 2026-10-06 by user nfjbill) are a 10-file, 16 KB launcher for a native executable that is not contained in the package. The postinstall script (bin/install.cjs) calls ensureNative() in dist/download.cjs, which downloads a 17-21 MB Brotli archive for the current platform from a non-npm host, https://registry-pxnpm.rdc.nfjbill.ren:20021/__static/srv/downloads/pxnpm/<version>/<platform>-<sha256>.br, decompresses it into a 52-72 MB executable under ~/.cache/pxnpm/native/<platform>/<sha256>/, sets mode 0755, and the launcher (dist/launcher.cjs line 54) later runs it with child_process.spawn. The manifest (dist/native-manifest.json) sets networkPolicy 'fixed', so the environment variables that would let a user supply a reviewed binary or a different download location are ignored; the archive and the executable are verified only against hashes shipped in the same package.

When run, dist/launcher.cjs prepare() deletes every registry and proxy setting from the user's environment (npm_config_registry, scoped registries, http(s)_proxy, no_proxy and the pnpm/pxnpm equivalents), rejects --registry and --proxy flags, and forces PXNPM_CONFIG_REGISTRY to https://registry-pxnpm.rdc.nfjbill.ren:20021/ and PXNPM_CONFIG_PROXY, HTTPS_PROXY and HTTP_PROXY to an authenticated proxy URL on the same host, port 20022 (a gost proxy), that is embedded in the file as a base64 string with the comment 'Filled only in the release staging directory; never store credentials in Git'. All package traffic of a user of this public package is therefore routed through the author's host, which can observe and alter it.

Nothing in the package name, the one-line README or the install output discloses that an executable will be fetched from a private host or that registry and proxy settings will be replaced. The JavaScript itself contains no data collection and no obfuscation beyond the base64 string. At the time of this report the download URL returns a 430-byte npm registry JSON document instead of the archive, so installation from outside the author's network fails at the checksum step and the executable could not be examined; its behavior is unknown. The same host is the hard-coded endpoint of yakuza0 2.23.40 by the same author (MAL-2026-13605).

Trigger: on install (postinstall) and on every run. Type: silent install-time download and execution of an unreviewable binary from a private host, with hijacking of registry and proxy settings.

---
_-= Per source details. Do not edit below this line.=-_

## Source: amazon-inspector (0ddd65b726b1457456e644252d4500a74faf4d13822f57d3b1c79823d6e8a57e)
pxnpm is a package-manager wrapper that, on every CLI invocation, strips the user's existing npm/pnpm registry, proxy, and auth settings from the environment and replaces them with a hardcoded author-controlled registry at https://registry-pxnpm.rdc.nfjbill.ren:20021/ and a credentialed HTTPS/HTTP proxy at https://pn:vt9b1ai@registry-pxnpm.rdc.nfjbill.ren:20022. The proxy URL, including its embedded Basic-Auth credentials, is shipped as a base64 string literal in launcher.cjs and decoded at runtime via Buffer.from(..., 'base64'), rather than appearing as a plain string. CLI flags such as --registry and --proxy are explicitly rejected with an error stating that external network settings are not accepted, so the routing cannot be overridden by the caller. As a result, every package resolution and tarball download performed through pxnpm transits an author-operated MITM point that can observe, log, or substitute the bytes of any dependency installed on the user's machine, including dependencies and transitive dependencies of unrelated projects built with this tool. The postinstall step additionally fetches a native engine binary from the same author domain (version-pinned and SHA-256 verified against a shipped manifest) and executes it as the package-manager engine on each invocation; the fetch mechanism itself matches a legitimate pinned-binary pattern, but the delivered engine runs with full control over the installer's package installations and inherits the forced-proxy routing. The combination of hardcoded credentialed interception of all dependency traffic, base64 concealment of the proxy URL, and refusal to honor user-supplied registry/proxy overrides is inconsistent with a transparent registry mirror or caching proxy and constitutes a dependency-tree interception channel against anyone who installs packages via pxnpm.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
