---
id: "MAL-2026-17196"
kind: "package"
aliases: ["MAL-2026-17196"]
title: "Malicious code in donutpromotion (PyPI)"
severity: "critical"
cvss: null
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "donutpromotion", "fixed": [], "affected": "= 0.1.0", "ecosystem": "pypi"}]
ecosystems: ["pypi"]
tags: ["malicious", "package"]
not_affected_if: []
published_at: "2026-09-27T08:55:47+00:00"
first_seen_at: "2026-10-26T20:52:03+00:00"
updated_at: "2026-10-26T21:08:21+00:00"
sources: [{"source": "osv-malicious", "url": "https://osv.dev/vulnerability/MAL-2026-17196", "first_seen_at": "2026-10-26T20:52:03+00:00"}]
---

# Malicious code in donutpromotion (PyPI)

## Affected

- pypi:donutpromotion affected = 0.1.0 fixed ?

## Timeline

- 2026-10-26T20:52:03+00:00 osv-malicious https://osv.dev/vulnerability/MAL-2026-17196

## From the sources

`donutpromotion` presents itself as a Minecraft SMP donation and rank-promotion helper. The published 0.1.0 sdist instead executes an encrypted downloader before setuptools processes the package.

The automated package report identified a critical `py-download-and-execute` signal at `donutpromotion/telemetry.py:99`: downloaded or embedded bytes are decrypted and passed to `exec()` with unrestricted builtins. Review of the cited path confirms the install trigger. When `setup.py` runs during build or installation, lines 6-7 import and call `donutpromotion.telemetry.check()` before `setup()` runs.

`telemetry.py:19` hardcodes `https://thisisafalsepositive.st/cdn/v2/promotion/manifest.json`. The loader skips obvious staging environments and hosts without a normal user profile, accepts a directive returned by that endpoint, and otherwise falls back to the encrypted blob shipped in `donutpromotion/_payload.py`. Lines 91-99 derive keys from a hardcoded seed, authenticate and decrypt the selected blob, and execute the resulting Python source. The authentication only restricts execution to publisher-controlled directives; it does not make the directive safe.

Offline static decryption of the embedded fallback, without executing it, reveals a second-stage downloader. It checks Windows BIOS strings for VMware, VirtualBox, QEMU, Xen and other virtualisation products; searches the process list for Wireshark, Procmon, Process Hacker, IDA, x64dbg and other analysis tools; calls `IsDebuggerPresent`; creates a one-time marker; and sleeps for a random interval. If those checks pass, it downloads `https://thisisafalsepositive.st/cdn/v2/9f4e7a2c1b8d.png`, treats compressed data hidden inside PNG chunks as a ZIP archive, extracts it, and starts the included `python.exe AppHost/main.py` as a detached, hidden background process.

The automated sandbox completed without observing the second-stage request; the source explicitly avoids staged environments and hosts without a normal user profile. The cited static `py-download-and-execute` path and the decrypted fallback establish the install-time chain independently.

Evidence: `setup.py:6-7` calls the loader during build/install; `donutpromotion/telemetry.py:19` sets the manifest endpoint; lines 62-99 select, authenticate, decrypt and execute the directive; `donutpromotion/_payload.py` contains the encrypted fallback.

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

## Source: amazon-inspector (ada85a54b2cc7d9770d7276da4b2e9983c29ad0e8e2187737415073b4f80d947)
setup.py imports donutpromotion.telemetry and invokes check() during pip install. check() fetches a JSON manifest from the hardcoded non-publisher domain https://thisisafalsepositive.st/cdn/v2/promotion/manifest.json, extracts an 'r' field, and if the fetch fails falls back to a ~4.4KB base64-encoded encrypted PAYLOAD embedded in _payload.py. The bytes are decrypted with ChaCha20+HMAC using a hardcoded passphrase from security.py and passed to exec(), granting the domain operator (or the shipped fallback) arbitrary code execution on the installer's machine. Detonation is gated: check() only proceeds when Documents or Downloads directories exist under the user home (via _is_real()) and aborts when DAS_STAGED=1 or DONUTPROMOTION_TELEMETRY=0 is set, evading build farms and analysis sandboxes while firing on developer workstations. setup.py wraps the whole invocation in a bare try/except pass to suppress errors. The README advertises offline Minecraft helper functionality, which is inconsistent with install-time network fetch and exec of remote content.

## Source: kam193 (26201e7959d7a736440fa6fb22ba7b9911c269b08460374d0a2db307ba6b0273)
During installation, obfuscated code is used to fetch code hidden in an image containing a Python application with a native extension module. This module holds an obfuscated infostealer which collects sensitive data and exfiltrates them to a C2 server retrieved from transaction history in the Polygon blockchain.


---

Category: MALICIOUS - The campaign has clearly malicious intent, like infostealers.


Campaign: 2026-09-donutautosellsrc


Reasons (based on the campaign):


 - infostealer


 - Downloads and executes a remote executable.


 - obfuscation


 - malware


 - native-extension


 - steganography


 - c2-in-blockchain


 - The package contains code to detect if it is running in a sandbox environment.

---

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