Package names repurposed to push malware on PyPI

A malicious PyPI package named termcolour reappeared in March as a three-stage downloader, illustrating how repurposing an abandoned package name can seed a supply-chain attack. The incident shows how PyPI’s name-reuse policy and lack of visibility into who removed a package can enable attackers to mislead developers and inject malware. Hashtags: #termcolour #Codecov

Keypoints

  • Malicious PyPI package named termcolour reappeared in March as a three-stage downloader targeting downstream Python developers.
  • PyPI allows reusing names of deleted packages under certain rules, creating a risk of repurposing abandoned names for malware.
  • The termcolour package appeared innocuous but contained colored.py with obfuscated and encrypted code that decrypts and executes a payload.
  • The decrypted payload reveals a simple three-stage downloader, with the second stage executed only on Linux.
  • The termcolour incident is not new: a prior version existed in 2021 and was removed in 2022, then reused maliciously in 2023.
  • Experiments by researchers showed a 17% success rate for reusing names of removed packages among 111 observed removals, highlighting a real risk.
  • There is a lack of transparency on PyPI about who removed a package, complicating efforts to assess risk and defend against repurposed names.

MITRE Techniques

  • [T1059.006] Python – The payload is decrypted and executed in Python, including use of the exec function masked behind a benign name. Quote: “the real purpose of which was difficult to discern from reading the code” and “executed — as function “b” is called.”
  • [T1027] Obfuscated/Compressed Information – The malicious code is encrypted in a very simple manner, and it is then decrypted in the next few lines of code. Quote: “The malicious code is encrypted in a very simple manner, and it is then decrypted in the next few lines of code.”
  • [T1105] Ingress Tool Transfer – Describes a “simple three-stage downloader” delivering payloads across stages. Quote: “it is a simple three-stage downloader, where the second stage is a script executed afterwards (although only if the platform is Linux).”
  • [T1059.004] Unix Shell – The second-stage script execution is conditioned on Linux, indicating shell/script interpreter activity on Unix-like systems. Quote: “(although only if the platform is Linux).”
  • [T1036] Masquerading – Names do not match between the PyPI package and the associated GitHub page, signaling deceptive disguising of the package identity. Quote: “The name of the package and the name on the GitHub page did not match.”
  • [T1195] Supply Chain Compromise – Repurposing abandoned package names to spread malware and start a supply-chain attack. Quote: “repurposing names is a strategy that is already being used by malicious actors to spread malware and start a supply-chain attack.”

Indicators of Compromise

  • [SHA1] Malicious termcolour packages – 67bdf8aeb709760e94d8ec741417d98dfb79c4c7, e691b3cb1abde57b42814d9b1aa9eb30803b64c6, and 2 more hashes
  • [Package name] termcolour – termcolour, lucija-package
  • [File name] colored.py – The payload is contained and decrypted within colored.py and then executed

Read more: https://www.reversinglabs.com/blog/package-names-repurposed-to-push-malware-on-pypi