sysmon.py
sysmon.py is a persistent Python backdoor referenced across multiple 2026 software supply-chain intrusions attributed in the reporting to TeamPCP. It is described as a follow-on implant used in campaigns linked to the Trivy attack, the CanisterWorm npm compromises, the Checkmarx KICS/OpenVSX compromises, and trojanized LiteLLM PyPI releases. On Linux systems, the malware is dropped to paths such as ~/.config/sysmon/sysmon.py, /root/.config/sysmon/sysmon.py, or /host/root/.config/sysmon/sysmon.py and persisted via a systemd user service, including names such as sysmon.service or a disguised "System Telemetry Service," to ensure restart on boot or continued execution without root on standard hosts. The implant polls attacker-controlled endpoints for follow-on payloads, including https://checkmarx.zone/raw and, in related reporting, behavior similar or identical to the sysmon.py payload from the Trivy attack. It uses delayed beaconing, periodically retrieves a URL, downloads a remote binary to /tmp/pglog, marks it executable, and launches it as a detached process. A kill-switch/dormant-state check ignores URLs containing youtube.com. In Kubernetes-aware variants, the malware adds persistence by using available service account access to enumerate nodes, deploy highly privileged pods in the kube-system namespace, escape to the host via hostPath-mounted root filesystems, and install sysmon.py plus a systemd service on cluster nodes, allowing persistence beyond the original CI or container context. The malware has been associated with credential-theft operations targeting CI environments, cloud credentials, Kubernetes secrets, SSH material, package-manager tokens, and developer infrastructure, but sysmon.py itself is specifically the persistent C2 backdoor component used to fetch and execute additional payloads.
Hunt this family in your stack
Mallory pivots from this family to the IOCs, detections, and named campaigns that touch your stack, and pages you when something new lands.
Groups observed using it
1 distinct threat actor attributed by public researchers. Open in Mallory to see the full evidence chain and overlapping campaigns.
As with the Trivy operation, this malware can drop a python script intended to download and install a follow-on payload... If it is run on a standard linux host, it creates hidden directories in the users home folder ~/.config/sysmon and writes the python backdoor there. The backdoor is the same as in the previous version, except it reads from https://checkmarx.zone/raw
Techniques & procedures
25 distinct techniques documented for this family, organized by ATT&CK tactic.
Initial Access
2 techniques
Initial Access
The dropper sleeps 5 minutes, then polls the ICP blockchain-hosted C2 for a second-stage payload URL, downloads it to /tmp/pglog , and executes it.
The KICS GitHub Action was compromised with credential-stealing malware by TeamPCP... The malicious code was injected in the same manner as the Trivy incident: The attacker staged imposter commits... and directly update all 35 tags in the project... Update 03/24: The "litellm" packages on PyPI have been trojanized... Both compromised extensions... contained identical payloads.
Execution
5 techniques
Execution
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
// Title: TeamPCP Process Execution Artifacts ... // MITRE ATT&CK TTP ID: T1059 ... action_process_image_name in ( "openssl" , "tar" , "curl" , "systemctl" , "python" )
Persistence
5 techniques
Persistence
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
The dropper sleeps 5 minutes, then polls the ICP blockchain-hosted C2 for a second-stage payload URL, downloads it to /tmp/pglog , and executes it.
Privilege Escalation
4 techniques
Privilege Escalation
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
Stealth
5 techniques
Stealth
On GitHub-hosted Linux runners, a Base64-encoded Python script is decoded and executed... On self-hosted runners, a different Base64-encoded Python script performs broad filesystem credential harvesting.
The primary exfiltration channel is an HTTPS POST to scan.aquasecurtiy[.]org — a typosquatted domain mimicking Aqua Security's legitimate aquasecurity.com... The choice of filename mimics PostgreSQL logging
If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence.
Credential Access
5 techniques
Credential Access
On GitHub-hosted Linux runners, a Base64-encoded Python script is decoded and executed with sudo. It locates the Runner.Worker process, reads its memory maps via /proc/{PID}/maps, and scrapes raw process memory via /proc/{PID}/mem looking for GitHub Actions secrets
It targets the following: ... Kubernetes configs and service account tokens ... Infrastructure-as-code secrets (Terraform state/vars, Ansible, Helm) ... TLS/SSL private keys ... .env files and API keys ... System files (/etc/passwd, /etc/shadow, shell histories)
If the script is run on a Kubernetes container that has sufficient permissions, it will attempt to deploy a highly privileged pod... The script checks to see if the file: /var/run/secrets/kubernetes.io/serviceaccount/token exists and if it does, it uses that token to query /api/v1/nodes.
Discovery
2 techniques
Discovery
Command and Control
3 techniques
Command and Control
...maintains ongoing access through a takedown-resistant C2 hosted on the Internet Computer Protocol. | The dropper sleeps 5 minutes, then polls the ICP blockchain-hosted C2 for a second-stage payload URL...
Exfiltration
2 techniques
Exfiltration
The persistence script polls https://checkmarx.zone/raw every 50 minutes for additional payloads... while True ... time.sleep(3000)
The primary exfiltration channel is an HTTPS POST to scan.aquasecurtiy[.]org... If the endpoint returns a non-2XX response and INPUT_GITHUB_PAT is available, the script falls back to exfiltrating through GitHub itself. It will create a public repository named tpcp-docs under the victim's GitHub account, create a timestamped release, and upload the encrypted bundle as a release asset.
IOCs tracked for this family
19 indicators attributed across vendor reports, sandbox runs, and researcher write-ups. Full values are available in Mallory.
IPs, domains, and DNS infrastructure linked to this family.
File hashes (MD5, SHA-1, SHA-256) from samples and reports.
Other indicator types observed in public reporting.
Recent activity
4 sources tracked across advisories, community write-ups, and news. New activity surfaces here as Mallory finds it.
A Linux persistence backdoor dropped by the malicious LiteLLM package payload. It is installed as a disguised system telemetry service, beacons to checkmarkr.zone/raw for commands, and provides persistent access on Linux hosts and Kubernetes nodes.
A persistent C2 backdoor dropped by the malicious litellm package. It is installed as a systemd user service, polls https://checkmarx.zone/raw roughly every 50 minutes, downloads arbitrary binaries, makes them executable, and runs them detached. In Kubernetes environments, it is also written onto host nodes for persistence and lateral compromise.
A Python backdoor dropped by the malicious setup.sh script. It persists on Linux hosts or Kubernetes nodes, polls attacker-controlled infrastructure for additional payload URLs, downloads and executes follow-on payloads, and is used to maintain access after the initial CI/container execution ends.
A Python backdoor payload referenced as highly similar or identical to the CanisterWorm second-stage implant, using an ICP canister dead-drop to retrieve a URL for a downloadable binary payload.
The version that knows your environment.
Match every observed IP, domain, and hash against your live telemetry.
Named campaigns wielding this family, with evidence pinned to each claim.
CVEs this family uses for access and lateral movement.
YARA, Sigma, Snort, and vendor rules, auto-deployed to your SIEM.
Every documented technique, ranked by evidence weight.
Reddit, Mastodon, and CTI community discussion around this family.