You just found a CVE PoC repo with a clean README, working code samples, and a handful of stars. You clone it, run pip install -r requirements.txt to get the dependencies working, and move on to testing the exploit. Except the exploit was never the payload — the pip install was.
TL;DR
- ChocoPoC is a remote access trojan distributed through trojanized GitHub PoC repositories for real, high-severity CVEs (FortiWeb, PAN-OS, Ivanti Sentry, and others).
- Infection happens through a malicious PyPI dependency chain: a package named
frintpulls inskytext, which ships a compiled native extension that silently loads instead of a readable Python module.- The payload is fetched from and exfiltrates data through Mapbox dataset infrastructure — a legitimate mapping API abused as covert C2.
- This isn’t an isolated incident. WebRAT (active since late 2025) and a 2023 VulnCheck-documented campaign used the same playbook — fake researcher personas, real CVE lures, malware payload.
- A Leiden University study found confirmed malicious indicators in 899 of 47,285 checked GitHub PoC repositories; follow-on analysis cited by BleepingComputer put the broader suspicious/malicious set as high as 10.3%.
Why This Matters to You
If you do vulnerability research, red teaming, or CTI validation work, you clone unfamiliar code from strangers on GitHub as part of your job description. That’s not a bad habit — it’s the job. ChocoPoC and its predecessors exist specifically because that workflow is predictable and hard to avoid.
This isn’t a “don’t download suspicious files” awareness poster. The operators behind these campaigns impersonate real researchers, reference real CVEs, and write code that partially works — enough to survive a skim-read before you run it.
Table of Contents
- The Campaign: What ChocoPoC Actually Does
- Anatomy of the Infection Chain
- The Extension Shadowing Trick
- This Is a Pattern, Not an Incident
- Why Researchers Specifically
- Did You Already Run It? Quick Self-Check
- MITRE ATT&CK Mapping
- What You Can Do Today
The Campaign: What ChocoPoC Actually Does
Sekoia identified at least seven GitHub repositories distributing ChocoPoC, each dressed up as a working exploit for a real, recent vulnerability:
| Lure CVE | Product |
|---|---|
| CVE-2025-64446 | Fortinet FortiWeb |
| CVE-2025-55182 | React2Shell |
| CVE-2025-14847 | MongoBleed (MongoDB) |
| CVE-2026-0257 | Palo Alto PAN-OS |
| CVE-2026-10520 | Ivanti Sentry |
| CVE-2026-50751 | Check Point VPN |
| CVE-2026-48908 | Joomla SP Page Builder |
These aren’t obscure or fabricated CVEs. YesWeHack and Sekoia describe them as real, high-profile vulnerability lures that security teams were actively searching for exploit code on, which is exactly what makes the tactic effective. A red teamer racing to validate whether PAN-OS is exploitable in a client environment doesn’t have time to audit every dependency in a stranger’s requirements file.
Once ChocoPoC lands, it isn’t subtle about what it wants: execute arbitrary commands and Python code, upload files from the host, pull saved passwords/cookies/autofill/history out of installed browsers, search the filesystem for documentation and config files, exfiltrate shell history and network configuration, and enumerate running processes. That’s a full reconnaissance-and-credential-theft loadout aimed at a machine that, by definition, has interesting things on it — VPN configs, internal tooling, client engagement notes, cloud credentials.
Sekoia’s telemetry shows roughly 2,400 downloads of the skytext dependency package, mostly from Linux-based systems — consistent with a target population of researchers and pentesters running Linux workstations or VMs rather than general consumers.
Anatomy of the Infection Chain
The chain is deliberately boring at every step except the last one, which is the point — nothing about pip install -r requirements.txt looks like an attack.
1. Victim finds/clones a GitHub repo claiming to PoC a real CVE2. requirements.txt (or setup.py) lists a dependency: "frint"3. pip installs frint from PyPI — looks like a normal helper package4. frint pulls in a second dependency: "skytext"5. skytext ships compiled native extensions, including `gradient.so` on Linux and `gradient.pyd` on Windows6. When the PoC imports the extension, its initialization routine runs and decrypts embedded code7. Decrypted code downloads the ChocoPoC payload from a Mapbox dataset8. ChocoPoC establishes persistence and begins collectionEarlier waves of the same campaign used differently-named packages — slogsec and logcrypt.cryptography — with near-identical logic. When PyPI or researchers flag one package name, the operators rename and republish rather than change the technique. That’s a strong signal this is an active, maintained operation, not a one-off dump.
The Extension Shadowing Trick
The one piece of this campaign worth understanding at a technical level, because it’s reusable against Python-based tooling: native extension precedence over source modules with the same import name.
When Python resolves an import such as import gradient, it searches sys.path for anything matching that module name — a .py source file, a package directory, or a compiled extension module (.so on Linux, .pyd on Windows). If a compiled extension and a plain Python module share a name and both are discoverable in the selected location, the compiled extension takes precedence.
# What the PoC repo's source tree appears to contain:# gradient.py <- looks like harmless, readable Python## What actually ships inside the PyPI package on disk:# gradient.py <- decoy source# gradient.so <- Linux compiled extension, wins import resolution# gradient.pyd <- Windows compiled extension, same idea## import gradient -> Python loads the compiled extension, not gradient.py# A source code review of the repo shows nothing malicious,# because the malicious code was never in the repo's source tree at all —# it's compiled into a binary fetched separately from PyPI.This is why “I read through the PoC script and it looked fine” isn’t a meaningful safety check here. The malicious logic doesn’t live in the code you’d naturally review — it lives in a compiled binary one dependency layer removed, which most people never open in a disassembler before running pip install.
This Is a Pattern, Not an Incident
ChocoPoC is the newest instance of a technique with a documented multi-year history:
WebRAT (active since ~September 2025). Documented by Kaspersky’s Securelist and covered by BleepingComputer, WebRAT spread through fake CVE exploit repositories specifically aimed at junior researchers and students — the demographic most likely to trust a polished README and a real-sounding CVE number without independently verifying either.
The “High Sierra Cyber Security” campaign (VulnCheck, active since ≥May 2023). Operators built an entire fake persona network — a nonexistent company, Twitter/X accounts, and headshots stolen from real researchers at firms like Rapid7 — to make trojanized zero-day PoCs for Chrome, Discord, Signal, WhatsApp, and Microsoft Exchange look credible. When repos got reported and taken down, the operators simply stood up new accounts and kept going.
The Leiden University baseline study. Researchers Soufian El Yadmani, Robin The, and Olga Gadyatskaya analyzed 47,285 downloaded GitHub repositories containing PoCs for CVEs from 2017–2021 and found 899 repositories with indicators of malicious intent. BleepingComputer’s 2022 coverage, based on additional researcher context, reported a broader suspicious/malicious set of 4,893 out of 47,313 tested repositories, or 10.3%, excluding confirmed fakes and prankware. The exact number depends on the threshold used, but the operational point is the same: malicious PoCs were common enough to make “random GitHub exploit repo” a real trust boundary, years before ChocoPoC and WebRAT.
The consistent thread across all three: attackers don’t need a novel technique. They need a real CVE number, a working-enough PoC, and patience.
Why Researchers Specifically
There’s a structural reason vulnerability researchers are a better target than random developers: urgency defeats caution.
When a critical CVE drops, there’s competitive pressure to be first — first to validate exploitability for a client, first to publish detection content, first to confirm whether a production system is actually at risk. That pressure pushes people toward running code faster and reviewing it less. Attackers exploit that exact tension: publish a PoC within hours of a CVE going public, before an official reference exploit exists, and you become the only source in town.
It also means the victim population self-selects for value. A researcher who successfully clones and runs a PAN-OS or FortiWeb PoC is, by definition, someone with hands-on access to environments running that software — often via a VPN client, cloud console session, or internal tooling that’s far more interesting to an attacker than a random home laptop.
There’s also an attribution wrinkle worth understanding. Sekoia found GitHub committer email addresses tied to ChocoPoC repos that overlap with an earlier, separate PoC-trojanizing operation from late 2025 — but the operators appear to primarily use compromised accounts, likely sourced from infostealer logs or credential-leak databases, rather than accounts they registered themselves. That matters operationally: reporting and banning a repo’s publisher account doesn’t necessarily touch the actual operator, and it means the “who’s behind this” question may never resolve to a single identifiable group the way the VulnCheck-documented “High Sierra Cyber Security” persona network eventually did.
Did You Already Run It? Quick Self-Check
If you’ve installed a PoC dependency in the last few weeks and want to sanity-check your environment before reading further, look for these signals rather than assuming you’re fine because nothing looks obviously wrong — ChocoPoC’s entire design goal is to not look wrong:
- Installed package inventory:
pip show frint skytext slogsec 2>/dev/null(or checkpip listoutput) for any of the known package names from this campaign or its earlier iterations. Absence doesn’t guarantee safety — the operators rename packages when one gets flagged — but presence is a definite compromise. - Unexpected compiled extensions in pure-Python-looking packages:
find ~/.venv -name "*.so" -newer <install-date-reference>(Linux) or the.pydequivalent on Windows, scoped to virtual environments used for PoC testing. A “helper” or “utility” package that ships a native binary with no obvious reason to isn’t automatically malicious, but it’s a strong reason to open it in a disassembler before trusting it. - Outbound connections to mapping/geodata APIs from a research VM that has no legitimate reason to talk to Mapbox or similar services — check proxy or firewall logs, not just live
netstatoutput, since persistence mechanisms don’t always keep a connection open continuously. - Browser profile access from a Python process. Legitimate PoC exploit code has no reason to read Chrome’s
Login DataSQLite file or Firefox’skey4.db. If your EDR or host logging can show file access by process, that’s a high-confidence indicator on its own.
If you find any of these, treat the host as fully compromised — kill network access, rotate every credential that was ever active in that session (cloud tokens, VPN certs, SSH keys, saved browser passwords), and rebuild rather than clean.
MITRE ATT&CK Mapping
| Tactic | Technique | ID |
|---|---|---|
| Initial Access | Supply Chain Compromise: Compromise Software Dependencies and Development Tools | T1195.001 |
| Execution | User Execution: Malicious File | T1204.002 |
| Stealth | Obfuscated Files or Information | T1027 |
| Command and Control | Application Layer Protocol: Web Protocols | T1071.001 |
| Credential Access | Credentials from Web Browsers | T1555.003 |
What You Can Do Today
If you regularly pull PoC code for CVE validation, red team ops, or CTI work, treat every unfamiliar repo as hostile by default until proven otherwise:
- Detonate in a disposable, network-isolated environment. A throwaway VM or container with egress restricted to only what the exploit genuinely needs (usually just the target). No shared credentials, no mounted home directory, no cloud metadata endpoint reachable.
- Read the dependency tree, not just the PoC script.
pip download --no-deps <package>and inspect what actually ships before installing. Look specifically for compiled artifacts (.so,.pyd,.pyc-only distributions) in a package that has no obvious reason to ship native code. - Resolve dependencies before execution. Use a throwaway environment, inspect
pip install --dry-run --report <file>output where your pip version supports it, or generate a lockfile so you can see the full dependency graph before running the PoC. - Distrust stars, forks, and account age as trust signals. They’re free and attackers farm them. Check commit history depth, whether the account has any activity outside PoC repos, and whether the CVE writeup matches the vendor advisory in technical detail (attackers often skim the same public advisory you would).
- Prefer vendor or CNA-published PoCs and established researchers over the first repo that shows up in a GitHub search immediately after disclosure. Use vendor advisories, CNA records, and CISA KEV entries to validate the vulnerability context, not as proof that a random exploit repository is safe.
- If you’re building detection content, run known-clean exploit code from established researchers or write your own minimal PoC rather than sourcing from anonymous repos entirely — the time saved isn’t worth the box you might burn.
- Monitor egress from research VMs for unexpected destinations, including “boring” infrastructure like mapping, analytics, or CDN APIs — exactly the kind of service ChocoPoC abused for C2 because it doesn’t look like C2 in a firewall log.
Related Posts
- Quasar Linux QLNX: A Developer Workstation RAT Built for Supply Chain Access — another campaign specifically targeting developer/researcher machines for the access behind them, not the machine itself.
- The Package You Trusted: How the Axios Supply Chain Attack Happened — how a single trusted package compromise cascades through everyone who depends on it.
- Shai-Hulud: The Open-Source GitHub Actions Token Harvester — a related developer-tooling attack surface, this time against CI/CD pipelines instead of local clones.
- The Clean Repo Trap: AI Coding Agents and the Trust Boundary Problem — the same “code that looks clean isn’t proof it’s safe” trust problem, applied to AI coding agents instead of human researchers.
Sources
- BleepingComputer — New ChocoPoC malware targets researchers via trojanized PoC exploits
- YesWeHack/Sekoia — Don’t eat the ChocoPoCs: how vulnerability researchers were repeatedly targeted by trojanised exploits
- arXiv — Beyond the Surface: Investigating Malicious CVE Proof of Concept Exploits on GitHub
- Securelist (Kaspersky) — Webrat distributed via GitHub
- Help Net Security — Budding infosec pros and aspiring cyber crooks targeted with fake PoC exploits
- VulnCheck — Fake Security Researcher GitHub Repositories Deliver Malicious Implant
- Uptycs — Beware of Fake PoC Repositories & Malicious Code on GitHub
- BleepingComputer — Thousands of GitHub repositories deliver fake PoC exploits with malware (Leiden University study)
- MITRE ATT&CK — T1195.001 Compromise Software Dependencies and Development Tools
- MITRE ATT&CK — T1204.002 User Execution: Malicious File
- MITRE ATT&CK — T1027 Obfuscated Files or Information
- MITRE ATT&CK — T1071.001 Application Layer Protocol: Web Protocols
- MITRE ATT&CK — T1555.003 Credentials from Web Browsers