Aller au contenu

Supply chain attacks : ce que Trivy, XZ et SolarWinds changent pour vos déploiements

Cryptolab.re
Auteur
Cryptolab.re
Cryptolab est un blog personnel où je documente mes expérimentations techniques : infra, self-hosting, réseau, crypto et projets parfois inutiles, souvent instructifs.
Sommaire

Le 19 mars 2026, un groupe identifié comme TeamPCP a publié une version malveillante de Trivy, le scanner de vulnérabilités le plus utilisé du monde conteneurisé.

L’attaque est exemplaire dans sa mécanique.

TeamPCP a compromis le compte aqua-bot qui gère les releases de Trivy. Avec ce token, ils ont poussé un commit qui remplaçait actions/checkout par un fork malveillant, téléchargeant du code depuis un domaine typosquatté. Le flag --skip=validate de goreleaser était activé pour contourner la validation.

En quelques minutes, 76 des 77 tags de version de trivy-action étaient force-pushés vers des commits infectés. Les 7 tags de setup-trivy étaient tous remplacés.

Le payload était un credential stealer : dump de la mémoire du runner GitHub via /proc/<pid>/mem, sweep de 50+ chemins pour SSH keys, tokens AWS/GCP/Azure, secrets Kubernetes, Docker configs, fichiers .env, identifiants de base de données, wallets crypto. Les données étaient chiffrées en AES-256-CBC avec RSA-4096 et exfiltrées vers un serveur C2.

Trois jours plus tard, des images Docker Hub v0.69.5 et v0.69.6 arrivaient avec le même payload. Et un ver npm, CanisterWorm, se propageait via le paquet containers-check.

Aqua Security a détecté l’intrusion initiale fin février 2026 et avait rotationné des credentials. Mais la rotation n’était pas atomique. TeamPCP a gardé un accès résiduel via des tokens non révoqués.

Le plus frappant n’est pas la sophistication. C’est la banalité du point d’entrée : un token CI mal rotationné. Et la confiance qu’on accorde à un outil qui est censé améliorer la sécurité.

En bref
#

  • Une attaque supply chain ne cible pas votre code. Elle cible ce que votre code consomme.
  • Trivy (mars 2026) : credential stealer via 76 tags GitHub Actions empoisonnés, ver npm, images Docker Hub malveillantes.
  • XZ Utils (2024) : backdoor dans liblzma via un contributeur infiltré sur deux ans.
  • SolarWinds (2020) : modification du processus de build, code signé valide, 18 000 clients exposés.
  • Les petits déploiements ne sont pas épargnés : watchtower, curl | bash, images Docker Hub non auditées.
  • Les outils de mitigation existent : SBOM, signature, pinning, scanners. Encore faut-il les utiliser.
  • L’objectif n’est pas la sécurité parfaite. C’est de réduire la surface et d’accélérer la détection.

Qu’est-ce qu’une attaque supply chain
#

Une attaque supply chain ne vise pas directement votre infrastructure. Elle contamine ce que votre infrastructure consomme.

Schématiquement, trois conditions sont nécessaires :

  1. Une relation de confiance. Vous installez un paquet, vous tirez une image Docker, vous appelez une dépendance. Vous ne vérifiez pas son contenu.
  2. Un point d’insertion. L’attaquant parvient à introduire du code malveillant dans ce que vous consommez : compromission d’un mainteneur, usurpation d’identité, registre de paquets compromis.
  3. Une exécution automatisée. Le code malveillant s’exécute parce que le mécanisme de mise à jour, de build ou de déploiement est lui-même automatisé et non supervisé.

Ce qui rend ces attaques difficiles à défendre, c’est que chaque étape est légitime individuellement. Vous faites apt upgrade. Vous mettez à jour vos actions GitHub. Vous rebuild une image Docker. Rien n’est anormal.

C’est la combinaison qui pose problème.

Différence avec une compromission classique
#

Dans une attaque classique, l’attaquant doit trouver un point d’entrée sur votre infrastructure : un service exposé, un mot de passe faible, une vulnérabilité non patchée.

Dans une attaque supply chain, l’attaquant n’a pas besoin de vous cibler directement. Il cible un fournisseur en amont. Si vous consommez ce fournisseur, vous êtes exposé par transitivité.

C’est une externalisation du risque : vous déléguez la sécurité d’un composant, mais pas la responsabilité de l’incident.

Types d’attaques
#

Les attaques supply chain ne suivent pas un schéma unique. Voici les mécanismes documentés.

Contributeur malveillant
#

Un contributeur légitime ou infiltré introduit du code malveillant dans les sources. Le code est publié comme une mise à jour normale. Le cas XZ Utils est le plus connu : l’attaquant a passé deux ans à gagner la confiance avant d’injecter un backdoor.

Compromission de compte mainteneur
#

Le compte d’un mainteneur est volé via phishing, credential stuffing, ou vol de token CI. C’est le mécanisme de l’attaque Trivy (compte aqua-bot), de Codecov (compte Twitter), et de nombreux incidents npm.

Attaque de registre de paquets
#

Le registre lui-même est compromis, pas un paquet spécifique. Tous les paquets servis depuis ce registre sont potentiellement altérés. C’est plus rare car les registres majeurs (npm, PyPI, crates.io) ont des équipes de sécurité dédiées, mais des cas existent.

Typosquatting et dependency confusion
#

L’attaquant publie un paquet dont le nom ressemble à un paquet populaire (log-in pour login, requets pour requests) ou exploite la priorité des registres internes vs publics dans les gestionnaires de paquets. C’est simple, automatisable, et toujours efficace.

Dépendance transitive contaminée
#

Le paquet direct n’est pas malveillant. Mais l’une de ses dépendances, peut-être à cinq niveaux de profondeur, l’est. L’attaquant cible un paquet peu populaire mais qui a des milliers de dépendants indirects. C’est le mécanisme de l’attaque event-stream (npm, 2018).

Pipeline CI/CD compromis
#

Le code source est propre. Le processus de build est propre. Mais le pipeline qui assemble, signe et déploie le logiciel a été altéré. SolarWinds en est l’exemple type. CircleCI (2023) aussi : des tokens CI ont été volés et ont exposé des centaines de dépôts.

Serveur de dépendances détourné
#

Un serveur qui distribue des bibliothèques ou des scripts est compromis. Les applications qui chargent du contenu depuis ce serveur téléchargent du code malveillant à l’exécution. Polyfill.io (2020) est le cas le plus marquant : un service JavaScript tiers utilisé par des milliers de sites a servi du code malveillant.

Cas réels
#

Trivy (mars 2026)
#

TeamPCP a compromis le token CI aqua-bot. Aqua Security avait détecté l’intrusion fin février et rotationné les credentials, mais la rotation n’était pas atomique. Avec l’accès résiduel, TeamPCP a publié Trivy v0.69.4 contenant un credential stealer, et force-pushé 76 des 77 tags de trivy-action vers des commits malveillants. Les 7 tags de setup-trivy ont été intégralement remplacés.

Le payload récoltait la mémoire du runner GitHub, les credentials cloud (AWS, GCP, Azure), les tokens Kubernetes, les clés SSH, les fichiers .env et les wallets crypto. Les données étaient chiffrées avant exfiltration. Trois jours plus tard, des images Docker Hub v0.69.5 et v0.69.6 étaient publiées avec le même payload, et un ver npm (CanisterWorm) se propageait via containers-check. CVE-2026-33634.

XZ Utils (février 2024)
#

Un contributeur connu sous le pseudonyme Jia T. a passé deux ans à s’intégrer au projet XZ Utils. Il a soumis des correctifs légitimes, répondu à des issues, gagné la confiance des mainteneurs. Une fois les droits de commit obtenus, il a introduit un backdoor dans la librairie liblzma qui modifiait le comportement d’OpenSSH en mémoire. Le backdoor permettait d’injecter des clés SSH publiques sans modifier les fichiers de configuration sur le disque.

Andres Freund, développeur PostgreSQL chez Microsoft, a détecté le backdoor en remarquant des anomalies de performance dans SSH et des artefacts bizarres dans les scripts de build. Le cas est instructif parce qu’il montre qu’un attaquant patient peut contourner la relecture de code humaine.

SolarWinds Orion (décembre 2020)
#

APT29 (Cozy Bear) a compromis l’infrastructure de build de SolarWinds et injecté un backdoor dans le binaire de mise à jour d’Orion. Le code malveillant était signé avec le certificat officiel de SolarWinds, le rendant indétectable pour les mécanismes de signature standard. Environ 18 000 clients ont téléchargé la version compromise, dont des agences gouvernementales américaines.

FireEye a détecté l’incident lors d’une investigation interne. La leçon est que la signature de code ne garantit pas le contenu : elle garantit l’identité du signataire. Si le signataire est compromis, la signature valide un binaire malveillant.

Codecov (avril 2021)
#

Le compte Twitter de Codecov a été compromis et a publié un lien vers un script shell malveillant hébergé sur codecov.io. Le script volait les variables d’environnement des pipelines CI : tokens GitHub, clés API, credentials de déploiement. Beaucoup de projets open source avaient intégré ce script dans leurs GitHub Actions sans le relire. La leçon porte sur la confiance implicite accordée à un script parce qu’il provient du domaine officiel du projet.

event-stream (npm, 2018)
#

Un attaquant a contacté le mainteneur du paquet event-stream, qui faisait 2 millions de téléchargements par semaine, et a obtenu les droits de publication. Il a ajouté une dépendance apparemment anodine, flatmap-stream, qui contenait un cryptominer ciblant les portefeuilles Bitcoin de l’application Copay. Le code malveillant est resté discret pendant des mois parce qu’il ne s’activait que dans un contexte très spécifique. Détecté par un utilisateur qui a remarqué des appels réseau inexpliqués.

Polyfill.io (2018-2020)
#

Le développeur principal de Polyfill.io a abandonné le projet en 2018. Le service déployé n’était plus maintenu, mais des milliers de sites web continuaient de charger le script Polyfill.io dans leurs pages. En 2020, l’infrastructure a été compromise et servait du JavaScript malveillant aux visiteurs. Le cas illustre un angle mort classique : un projet open source non maintenu mais toujours utilisé, et l’infrastructure qui devient un vecteur d’attaque sans modification du code source.

ua-parser-js et npm (2022-2024)
#

Le mainteneur de ua-parser-js n’a plus répondu. Des comptes ont été compromis et des versions malveillantes publiées. En novembre 2024, les paquets eslint et flat ont subi le même sort, avec un payload ciblant les variables d’environnement AWS et les fichiers SSH. eslint est l’une des dépendances les plus installées sur npm. Les versions compromises ont été retirées rapidement mais avaient déjà été téléchargées des milliers de fois.

3CX Desktop App (mars 2023)
#

Un groupe nord-coréen (UNC4736) a compromis l’environnement de build de 3CX. Le logiciel de build lui-même a été altéré, produisant des binaires signés contenant un backdoor qui récoltait des informations système et communiquait avec des serveurs C2. La chaîne d’infection incluait des extensions Chrome malveillantes. 3CX compte 600 000 clients, dont Mercedes-Benz, American Express et la NHS. CrowdStrike et SentinelOne ont détecté les anomalies dans les artefacts signés, mais le backdoor était déjà déployé chez des centaines de milliers d’utilisateurs.

CircleCI (janvier 2023)
#

Un attaquant a compromis un token CI chez CircleCI via un malware qui infectait un employé. Le token donnait accès aux secrets de build stockés dans CircleCI. Tous les projets configurés avec des secrets ont été potentiellement exposés — tokens GitHub, clés SSH, credentials cloud. CircleCI a détecté l’activité anormale et publié un avis immédiat, mais des centaines d’organisations ont dû rotationner leurs credentials en urgence, certaines mettant des semaines à auditer l’impact réel.

Tableau comparatif
#

CasAnnéeVecteurType de payloadDurée d’expositionDétection
Trivy2026Token CI compromisCredential stealer, ver npm3h-12h selon composantRotation incomplète détectée
XZ Utils2024Contributeur infiltréBackdoor SSH~2 ans d’infiltrationAnomalies de performance
SolarWinds2020Build compromisBackdoor C2~9 moisInvestigation interne
Codecov2021Compte TwitterScript CI malveillantQuelques heuresSignalement utilisateur
event-stream2018Transfert d’ownershipCryptominer~2 moisAnalyse de trafic réseau
Polyfill.io2020Infrastructure non maintenueJS malveillantAnnéesReprise communautaire
3CX2023Build compromisBackdoor + Chrome ext.Plusieurs semainesEDR / SOC
CircleCI2023Token employéVol de secretsNon documentéMonitoring interne

Pourquoi les homelabs et les petits déploiements sont aussi concernés
#

Les attaques supply chain ne visent pas que les grandes entreprises. En réalité, les petits déploiements ont souvent moins de défense en profondeur.

Le problème du curl | bash
#

C’est la méthode d’installation la plus courante dans l’écosystème self-hosted et DevOps :

curl -sSL https://example.com/install.sh | bash

Tant que le script est légitime, ça fonctionne. Si le serveur ou le compte GitHub du projet est compromis, vous exécutez du code arbitraire sans vérification. Aucun contrôle d’intégrité. Aucune signature.

Les projets sérieux publient des checksums, des signatures GPG, ou utilisent des mécanismes comme cosign. Mais combien d’utilisateurs vérifient réellement la signature avant d’exécuter ?

Watchtower et les mises à jour automatiques
#

Watchtower est un outil populaire dans les homelabs : il surveille les conteneurs en cours d’exécution et met automatiquement à jour les images vers le tag latest. Le projet n’est plus maintenu depuis 2024 : la dernière image Docker date de plus de deux ans.

C’est le genre de dépendance qu’on oublie. Elle tourne, elle fonctionne, mais personne ne vérifie si elle reçoit encore des mises à jour de sécurité.

Si une image que vous utilisez est compromise (comme les images Trivy v0.69.4-0.69.6 sur Docker Hub), Watchtower la déploie sans poser de question. Vous avez automatisé la confiance.

docker run -d --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower

C’est pratique. C’est aussi un vecteur d’attaque parfait.

Les images Docker communautaires
#

Docker Hub héberge des millions d’images. Beaucoup sont officielles, beaucoup ne le sont pas. Les images avec le tag latest ou sans digest sont opaques : vous téléchargez un binaire sans savoir ce qu’il contient.

docker pull nginx:latest
# vs
docker pull nginx:1.27.0@sha256:c26a7473...

La première version peut changer à tout moment. La seconde est figée à un hash vérifiable.

Les actions GitHub copiées sans review
#

Dans les homelabs et les projets personnels, il est tentant d’utiliser une action GitHub trouvée sur le Marketplace sans lire son code source. L’attaque Trivy a montré qu’une action de confiance peut être compromise rétroactivement via un force-push de tags.

# Mauvais : tag flottant
uses: aquasecurity/trivy-action@0.34.0

# Correct : SHA fixe
uses: aquasecurity/trivy-action@abc123def456...

Comment se protéger des attaques supply chain
#

Concepts clés : SBOM, SLSA, signature
#

Avant de parler des outils concrets, trois concepts à connaître.

SBOM (Software Bill of Materials)
#

Un SBOM est un fichier structuré qui liste toutes les dépendances d’un logiciel, leurs versions, licences et relations transitives. Les formats standards sont SPDX et CycloneDX.

# Générer un SBOM avec syft
syft packages nginx:latest -o spdx-json > nginx-sbom.json

Sans SBOM, vous ne pouvez pas savoir ce que vous exécutez vraiment. C’est la base de toute analyse supply chain.

SLSA (Supply-chain Levels for Software Artifacts)
#

SLSA est un framework de maturité pour la sécurité de la chaîne de livraison. Il va de SLSA 1 (build documenté) à SLSA 4 (build reproductible, provenance vérifiable).

La plupart des projets open source sont à SLSA 0 ou 1. Atteindre SLSA 3+ demande des builds reproductibles, une signature des artefacts, et un environnement de build isolé et documenté.

Signature et provenance
#

Signer un artefact prouve qui l’a construit (identité). La provenance décrit comment il a été construit (environnement, dépendances, commande).

Sigstore / cosign simplifie la signature sans gestion de clés complexes :

cosign sign --key cosign.key ghcr.io/user/image:tag
cosign verify --key cosign.pub ghcr.io/user/image:tag

Boîte à outils concrète
#

Voici les outils disponibles aujourd’hui, ce qu’ils font, et comment les utiliser.

cosign (sigstore)
#

Signature et vérification d’images de conteneurs.

# Vérifier une image signée
cosign verify ghcr.io/user/image:tag \
  --certificate-identity mail@example.com \
  --certificate-oidc-issuer https://accounts.google.com

# Signer une image
cosign sign ghcr.io/user/image:tag

syft (anchore)
#

Génération de SBOM. Prend une image Docker, un répertoire, ou un fichier.

# Générer un SBOM
syft packages nginx:latest -o spdx-json

# Format table pour lecture rapide
syft packages nginx:latest -o table

grype (anchore)
#

Scan de vulnérabilités basé sur un SBOM. Utilise les mêmes bases que Trivy.

# Scanner une image
grype nginx:latest

# Scanner à partir d'un SBOM
grype nginx-sbom.json

# Sortie avec sévérité
grype nginx:latest --only-severity critical,high

osv-scanner (Google)
#

Scanner de vulnérabilités basé sur la base Open Source Vulnerabilities (OSV). Simple, rapide, sans base locale.

# Scanner un répertoire
osv-scanner scan -r .

# Scanner un lock file
osv-scanner scan -r ./package-lock.json

# Scanner une image Docker
osv-scanner scan -r docker://nginx:latest

Trivy (ironie assumée)
#

Oui, Trivy peut scanner ses propres dépendances et détecter les CVE.

# Scanner une image
trivy image nginx:latest

# Scanner avec sévérité minimale
trivy image --severity CRITICAL,HIGH nginx:latest

Le risque n’est pas d’utiliser Trivy. Le risque est de faire confiance aveuglément à son canal de distribution. Utilisez toujours un digest ou une version spécifique.

Dependabot (GitHub)
#

Analyse automatique des dépendances et PR de mise à jour intégrée à GitHub. Il s’active dans les settings du dépôt et supporte npm, pip, Go, Maven, Gradle, Docker, et les GitHub Actions. Il alerte sur les vulnérabilités connues dans les dépendances directes et transitives et génère des PR de mise à jour.

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"

Renovate
#

Alternative plus configurable à Dependabot. Supporte plus d’écosystèmes et offre des fonctionnalités comme le pinning automatique des digests Docker.

// renovate.json
{
  "extends": ["config:base"],
  "docker": {
    "pinDigests": true
  },
  "npm": {
    "pinVersions": true
  }
}

Ce que vous pouvez faire ce week-end
#

Si vous ne retenez qu’une chose : vous ne pouvez pas auditer tout ce que vous consommez. Mais vous pouvez réduire la surface. Voici les actions par ordre de priorité.

1. Vérifier l’intégrité de vos images Docker
#

# Lister les images et voir si elles utilisent un digest
docker images --digests

# Vérifier une image spécifique
docker inspect --format='{{index .RepoDigests 0}}' nginx:latest

# Scanner avec Trivy ou grype avant déploiement
grype nginx:latest

Si vos images n’ont pas de digest, vous utilisez des tags flottants. Passez à des versions fixes.

2. Pinner les versions et digests
#

# docker-compose.yml : mauvais
image: nginx:latest

# Correct
image: nginx:1.27.0@sha256:c26a7473...

Pour les dépendances de projet :

# Python
pip freeze > requirements.txt

# Node.js : package-lock.json est votre ami
npm audit

# Go
go list -m all

3. Vérifier les signatures de paquets
#

# apt vérifie les signatures GPG automatiquement
apt-get update 2>&1 | grep -E "(GPG|signature|NO_PUBKEY)"

# cosign ne fonctionne que si l'image est signée (peu d'images publiques le sont)
cosign verify ghcr.io/org/image:v1 --certificate-identity mail@example.com

4. Scanner les lock files avec OSV
#

osv-scanner scan -r .

Intégrez-le dans votre CI/CD. Gratuit, rapide, et sans dépendance externe.

5. Générer un SBOM de votre stack
#

# Pour votre projet
syft packages . -o spdx-json > sbom.json

# Pour vos conteneurs en cours
docker ps -q | xargs -I {} sh -c 'docker inspect {} | jq -r ".[].Config.Image"'

6. Sécuriser les runners CI/CD
#

# Vérifier les tokens GitHub exposés
gh secret list

# Pour les runners auto-hébergés : isoler par projet
# Utiliser des runners éphémères
# Ne jamais exposer les secrets de production aux runners publics

7. Configurer un plan de réponse
#

  1. Identifier les paquets concernés (paquet, version, machines)
  2. Isoler les processus infectés
  3. Retirer la version compromise (downgrade, réinstallation depuis source vérifiée)
  4. Rotationner tous les secrets exposés
  5. Vérifier les traces d’accès post-compromission
  6. Surveiller les systèmes impactés

8. Accepter le risque résiduel
#

Aucune de ces mesures ne supprime le risque. Mais elles transforment une compromission aveugle en un incident détectable.

Le danger n’est pas de manquer une attaque. C’est de ne pas savoir qu’elle a eu lieu.

Conclusion
#

Les attaques supply chain sont devenues un risque structurel du développement logiciel. Chaque année apporte son lot de cas : Trivy en 2026, XZ Utils en 2024, SolarWinds en 2020, et des dizaines d’incidents npm et PyPI entre deux.

Ce qui est frappant, c’est la constance des mécanismes. Ce n’est jamais la faille zero-day sophistiquée qui est le point d’entrée. C’est un token mal rotationné, un contributeur pas assez vérifié, un compte non surveillé.

La bonne nouvelle, c’est que les outils existent. SBOM, SLSA, cosign, grype, osv-scanner, syft, Dependabot, Renovate : ce n’est plus un problème sans solution. C’est un problème de volonté et de priorisation.

La mauvaise nouvelle, c’est que la plupart des déploiements, surtout dans les homelabs et les petites équipes, n’utilisent aucun de ces outils.

Si ce week-end vous ne faites qu’une chose : pinnez vos versions, vérifiez que vos images Docker ont un digest, et lancez osv-scanner scan -r . sur vos projets. C’est peu. C’est déjà beaucoup plus que la majorité des déploiements.


Sources
#

Sources consultées le 27 mai 2026 :

Articles connexes

Nginx RIFT (CVE-2026-42945) : comprendre la faille vieille de 18 ans

La CVE-2026-42945, surnommée Nginx RIFT, touche le module ngx_http_rewrite_module de Nginx, un composant historique introduit en 2008. Selon les chercheurs à l’origine de la découverte, la vulnérabilité peut mener, dans certaines conditions, à une corruption mémoire exploitable pouvant aller jusqu’à une exécution de code arbitraire (RCE). Un PoC public est déjà disponible, ce qui réduit rapidement le coût d’entrée pour tester l’exploitation.

Ubuntu Server 26.04 LTS : ce qu'il faut savoir avant de migrer

··2469 mots·12 mins
Ubuntu 26.04 LTS est sortie le 23 avril 2026 sous le nom Resolute Raccoon. Pour un poste desktop, c’est une nouvelle LTS avec GNOME 50, Wayland et quelques changements visibles. Pour un serveur, c’est autre chose : une base qui peut rester en production pendant plusieurs années, avec un nouveau noyau, une pile crypto plus stricte, des paquets serveur mis à jour, des changements de comportement sur des services courants, et une stratégie de support à bien comprendre avant de lancer un do-release-upgrade. Je regarde donc Ubuntu 26.04 LTS sous l’angle qui m’intéresse le plus ici : serveurs, VPS, homelab, cloud, sécurité et migration propre.