Threat reportMalwareTL-2026-0467
OceanLotus (APT32) PyPI Supply Chain Campaign — ZiChatBot Cross-Platform Malware via uuid32-utils, termncolor & colorinal Wheels Using Zulip REST API for C2
OceanLotus (APT32) PyPI Supply Chain Campaign (TL-2026-0467), also tracked as ZiChatBot Campaign, is a high-severity malware campaign, first published 2026-05-06. It is attributed to APT32 (Vietnam) with medium confidence, affects Python Software Foundation Python Package Index (PyPI), maps to 21 MITRE ATT&CK techniques (T1027, T1036.005, T1053.003), and is covered by 9 detection rules and 42 indicators of compromise.
- Severity
- HIGHAssessed severity
- CVEs
- 0None referenced
- Techniques
- 21MITRE ATT&CK
- Actors
- 1APT32
- Detection rules
- 9SPL · KQL · Sigma
- IOCs
- 42Indicators of compromise
Key facts for TL-2026-0467
- Threat ID
- TL-2026-0467
- Also known as
- ZiChatBot Campaign, Operation ZiChatBot, OceanLotus PyPI Wheel Campaign, termncolor/colorinal supply chain attack
- Severity
- HIGH
- Status
- MONITORING
- Category
- MALWARE
- First published
- Last reviewed
- Attribution
- APT32
- Attribution confidence
- MEDIUM
- Nation-state nexus
- Vietnam
- Motivation
- ESPIONAGE
- Target sectors
- technology, software-development, open-source, government, defense, telecommunications, automotive, pharmaceutical, research-academia
- Target regions
- Southeast Asia, ASEAN, North America, Europe, Global (developer ecosystem)
- Detection rules
- 9
- Indicators of compromise
- 42
Malware and tooling in OceanLotus (APT32) PyPI Supply Chain Campaign
Malware and tooling: ZiChatBot, Zulip Cloud (legitimate SaaS), Zulip REST API (custom ZiChatBot)
How OceanLotus (APT32) PyPI Supply Chain Campaign works
Kaspersky GReAT attributed a PyPI supply chain campaign to OceanLotus (APT32) involving three malicious wheel packages — uuid32-utils, termncolor and colorinal — uploaded between 10-22 July 2025 that drop a previously unknown cross-platform malware family named ZiChatBot. The malware abuses the Zulip team-chat REST API on the helper.zulipchat.com organization (now deactivated) as a covert C2 channel, weaponising a benign vcpktsvr.exe via DLL side-loading of libcef.dll on Windows and a /tmp/obsHub/obs-check-update ELF on Linux. Attribution to OceanLotus is supported by Kaspersky's Threat Attribution Engine which matched dropper decompression and decryption logic with 64% similarity to known APT32 droppers; an earlier Zscaler ThreatLabz disclosure in August 2025 covered the termncolor/colorinal cluster without naming the actor.
Overview -------- Between 10 July and 22 July 2025, three malicious Python wheel packages were published to the Python Package Index (PyPI) by accounts laz**** (tutamail.com) and sym**** (proton.me): uuid32-utils (multiple 1.x.x versions), colorinal 0.1.7 and termncolor 3.1.0. termncolor depends on colorinal so installing termncolor pulls in the malicious chain; uuid32-utils carries the dropper directly. colorinal had ~529 downloads and termncolor ~355 downloads before removal. All three packages were taken down by PyPI maintainers, and the attacker-controlled Zulip organisation "helper" (helper.zulipchat.com) was officially deactivated by Kandra Labs. Kaspersky's Securelist disclosure on 6 May 2026 attributed the campaign to OceanLotus (APT32) — a Vietnam-aligned espionage group — based on a 64% similarity match between the dropped loader's decryption/decompression logic and a known OceanLotus dropper, surfaced by Kaspersky's Threat Attribution Engine. The malware family was named ZiChatBot for its use of the Zulip Chat platform as command and control.
Windows Infection Chain ------------------------ 1. The user runs `pip install termncolor` (or installs uuid32-utils). The wheel registers `colorinal\unicode.py` which is imported by `__init__.py`. 2. `is_color_supported()` in unicode.py loads the bundled native module `terminate.dll` into the running Python process and invokes the exported function `envir` with the parameter `xterminalunicod` (UTF-8 encoded). 3. terminate.dll AES-CBC decrypts an embedded blob and drops two files into `%LOCALAPPDATA%\vcpacket\` — a legitimate signed Microsoft binary `vcpktsvr.exe` (the side-loading host) and the malicious `libcef.dll` (the ZiChatBot payload). 4. vcpktsvr.exe is launched, side-loads libcef.dll, and ZiChatBot begins execution. 5. Persistence is established by writing the registry value `HKCU\Software\Microsoft\Windows\CurrentVersion\Run\pkt-update` pointing to `%LOCALAPPDATA%\vcpacket\vcpktsvr.exe`. 6. The dropper and unicode.py self-delete to reduce forensic surface.
Linux Infection Chain --------------------- 1. The Linux variant of the wheel ships terminate.so (and a variant Backward.so) which performs the equivalent decryption stage. 2. The ELF payload is dropped to `/tmp/obsHub/obs-check-update`. 3. Persistence is established with the user crontab entry: `5 * * * * /tmp/obsHub/obs-check-update`.
ZiChatBot — C2 over Zulip ------------------------- Unlike traditional malware ZiChatBot does not contact dedicated attacker infrastructure. Instead it authenticates to the Zulip Cloud REST API at `https://helper.zulipchat.com/api/v1/` using a hard-coded base64-embedded credential that decodes to `Morian-bot@helper.zulipchat.com:U8REXlI6Kf8qXB9rQzOPBiIA4brJ58qG`. It uses two fixed channel/topic pairs: one for posting harvested system information from the victim and one for fetching shellcode tasking. Shellcode is XOR-decoded with the three-byte key `3a7` and executed reflectively in the host process. The bot supports a single command — "execute shellcode received from server" — and acknowledges successful execution by sending the heart emoji (`:heart:`) reaction back to the C2 message. Strings, imports and configuration are protected with AES-CBC. Forensic analysis of the Zulip organisation showed three active operator users and 90,692 messages exchanged from 10 July 2025 onward.
Attribution ----------- Kaspersky Threat Attribution Engine reported a 64% similarity score between ZiChatBot's loader code (decryption and decompression routines, control-flow markers and string obfuscation) and a known OceanLotus dropper. OceanLotus (also tracked as APT32, SeaLotus, APT-C-00, Cobalt Kitty, Ocean Buffalo) is a Vietnam-nexus espionage actor with a long history of supply chain abuse, watering-hole operations and signed-binary side-loading targeting ASEAN governments, dissidents, automotive and pharmaceutical sectors. The choice of Zulip as a C2 channel is novel for the actor and represents the first publicly documented use of Zulip's REST API for C2 by a nation-state cluster.
Defensive Implications ---------------------- Developers and CI/CD pipelines that pull from public PyPI without pinning or hash-checking are the primary attack surface. The Zulip-as-C2 design defeats domain blocklists that allow productivity SaaS and bypasses TLS inspection by riding a legitimate, certificate-pinned vendor. Defenders should hunt for child processes of `python.exe` writing to `%LOCALAPPDATA%\vcpacket\`, registry Run-key writes named `pkt-update`, outbound TLS to `helper.zulipchat.com`, and any anomalous workstation traffic to `*.zulipchat.com` from hosts that do not normally use Zulip.
MITRE ATT&CK techniques used in TL-2026-0467
Defense Evasion
T1027 Obfuscated Files or Information; T1036.005 Match Legitimate Resource Name or Location; T1070.004 Indicator Removal: File Deletion; T1140 Deobfuscate/Decode Files or Information; T1574.001 DLL; T1620 Reflective Code Loading
Persistence
T1053.003 Scheduled Task/Job: Cron; T1547.001 Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder
Execution
T1059.006 Command and Scripting Interpreter: Python; T1106 Native API; T1204.002 User Execution: Malicious File
Command and Control
T1071.001 Application Layer Protocol: Web Protocols; T1102.002 Web Service: Bidirectional Communication; T1132.001 Data Encoding: Standard Encoding; T1573.001 Encrypted Channel: Symmetric Cryptography
Discovery
T1082 System Information Discovery
Initial Access
T1195 Supply Chain Compromise; T1195.002 Compromise Software Supply Chain
Resource Development
T1583.006 Acquire Infrastructure: Web Services; T1585.002 Establish Accounts: Email Accounts; T1587.001 Develop Capabilities: Malware
Affected products and versions in OceanLotus (APT32) PyPI Supply Chain Campaign
- Python Software Foundation — Python Package Index (PyPI)
Vulnerable versions: uuid32-utils 1.x.x; colorinal 0.1.7; termncolor 3.1.0
Fixed in: all three packages removed from PyPI - Microsoft — Windows
Vulnerable versions: Windows 10; Windows 11; Windows Server 2019; Windows Server 2022 - Linux — GNU/Linux distributions running CPython
Vulnerable versions: any glibc-based x86_64 distribution with Python 3 - Kandra Labs — Zulip Cloud (helper.zulipchat.com)
Vulnerable versions: organization 'helper'
Fixed in: organization deactivated by Zulip Trust & Safety
Remediation for OceanLotus (APT32) PyPI Supply Chain Campaign
Patches
- Remove uuid32-utils, colorinal 0.1.7 and termncolor 3.1.0 from any internal mirror or lockfile
- Upgrade to a pinned version from a vetted alternative (e.g. termcolor, colorama) for any project that referenced termncolor
Immediate actions
- Block all outbound traffic to helper.zulipchat.com at the perimeter and proxy
- Hunt endpoints for the file path %LOCALAPPDATA%\vcpacket\ and the Linux path /tmp/obsHub/
- Hunt the registry value HKCU\Software\Microsoft\Windows\CurrentVersion\Run\pkt-update and remove if present
- Hunt the cron entry '5 * * * * /tmp/obsHub/obs-check-update' on Linux developer hosts
- Quarantine any host that installed uuid32-utils, termncolor, or colorinal between 2025-07-10 and 2025-08-31
- Rotate developer credentials, SSH keys, npm/PyPI tokens and cloud API keys exposed to suspect workstations
Workarounds
- Restrict pip and npm installations from developer workstations to a curated internal index until hunt is complete
- Apply egress filtering on developer subnets to block direct internet pip/npm pulls
Longer-term hardening
- Mandate hash-pinned dependencies (pip install --require-hashes) in all CI/CD pipelines
- Deploy private PyPI mirror (Artifactory, devpi, Nexus) with allowlist of vetted packages and hold-window for new releases
- Enable PyPI 2FA enforcement and trusted-publisher OIDC for internal package publishers
- Deploy EDR rules covering DLL side-loading from %LOCALAPPDATA%\vcpacket\ and reflective shellcode execution under python.exe child processes
- Add SaaS-as-C2 detection for Zulip, Slack, Discord, Telegram and Mattermost API calls from non-business hosts
Weaknesses (CWE) in OceanLotus (APT32) PyPI Supply Chain Campaign
Timeline of OceanLotus (APT32) PyPI Supply Chain Campaign
- Earliest operator activity recorded inside the attacker-controlled 'helper' Zulip organization (per Zscaler ThreatLabz forensic review).
- First malicious wheel uploaded to PyPI by author 'laz**** (tutamail.com)' — uuid32-utils 1.x.x series begins publication.
- termncolor 3.1.0 and colorinal 0.1.7 uploaded to PyPI by author 'sym**** (proton.me)'; closes the July upload window. Zscaler ThreatLabz simultaneously discovers termncolor.
- Zscaler ThreatLabz publishes 'Supply Chain Risk in Python: Termncolor and Colorinal Explained', documenting the DLL side-loading chain and Zulip C2 but not naming an actor. PyPI removes the packages.
- The Hacker News, GBHackers, and Cybersecurity News publish coverage of the termncolor/colorinal cluster; npm sister-cluster (redux-ace, rtk-logger) reported in the same wave.
- Kandra Labs (Zulip) deactivates the 'helper' organization and revokes the Morian-bot@helper.zulipchat.com bot credential.
- Threat documented in Threadlinqs Intelligence as TL-2026-0467 with full IOC, MITRE and detection coverage.
- Kaspersky GReAT publishes Securelist analysis naming the malware family ZiChatBot, releasing additional uuid32-utils IOCs and attributing the campaign to OceanLotus (APT32) with 64% similarity per the Threat Attribution Engine.
- As of 2026-05-29, this specific campaign is contained: all three PyPI wheels (uuid32-utils, colorinal, termncolor) were removed and the helper.zulipchat.com C2 org was deactivated 2025-08-31, with no new beaconing since. But OceanLotus/APT32 remains a highly active Vietnam-nexus actor with ongoing supply-chain tradecraft, so resurgence is a live concern.
Sources cited for OceanLotus (APT32) PyPI Supply Chain Campaign
- OceanLotus suspected of using PyPI to deliver ZiChatBot malware
- Supply Chain Risk in Python: Termncolor and Colorinal Explained
- Malicious PyPI and npm Packages Discovered Exploiting Dependencies in Supply Chain Attacks
- Weaponized Python Package termncolor Uses Windows Run Key for Persistence
- uuid32-utils — Safety DB advisory
- MITRE ATT&CK Group G0050 — APT32 (OceanLotus)
- ESET malware-ioc OceanLotus indicators repository
Detection coverage for TL-2026-0467
As of 2026-05-06, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-0467 across Splunk SPL, Microsoft KQL and Sigma, covering 42 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.