Aller au contenu

GitHub Actions : empêcher l'empoisonnement du cache avec cache-mode

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

Un cache CI est souvent considéré comme un simple réglage de performance. Pourtant, les fichiers restaurés peuvent finir dans un chemin exécuté par le build : dépendances, scripts, objets compilés, outils téléchargés ou couches intermédiaires. Un cache modifié par un job peu fiable peut donc devenir un canal d’exécution dans un workflow plus privilégié.

Depuis le 10 septembre 2026, GitHub Actions permet de fixer explicitement les droits du cache avec cache-mode. La clé accepte quatre valeurs, read, write, write-only et none, au niveau du workflow ou d’un job. La fonction est disponible sur github.com pour tous les plans.

Le réglage le plus utile en pratique consiste à séparer les rôles : les validations de pull requests restaurent un cache en lecture seule, tandis qu’un workflow déclenché depuis une branche de confiance produit les nouvelles entrées. Les jobs de publication qui n’ont pas besoin du cache le désactivent complètement.

cache-mode impose une limite de droits appliquée par le service de cache. Il ne vérifie toutefois pas l’intégrité des fichiers déjà présents et ne corrige pas un workflow qui exécute du code non fiable avec des secrets.

En bref
#

  • cache-mode: read autorise la restauration, mais interdit l’enregistrement d’une nouvelle entrée.
  • cache-mode: write autorise la restauration et l’enregistrement.
  • cache-mode: write-only autorise l’enregistrement, mais pas la restauration.
  • cache-mode: none coupe tout accès au cache GitHub Actions.
  • Le réglage d’un job remplace celui défini au niveau du workflow.
  • Sans réglage explicite, GitHub utilise write pour un déclencheur considéré comme fiable et read pour un déclencheur peu fiable qui travaille dans la portée de la branche par défaut.
  • Déclarer explicitement write ou write-only sur pull_request_target, issue_comment ou workflow_run contourne cette protection par défaut. GitHub affiche alors une annotation d’avertissement.
  • Le mode est appliqué avec un jeton de cache limité. Il est distinct des droits définis dans permissions pour le GITHUB_TOKEN.
  • Un workflow réutilisable ne peut pas obtenir plus de droits de cache que la limite explicite de son appelant.
  • Un cache restauré reste une entrée non fiable : son contenu n’est ni signé ni vérifié par GitHub.

Comment fonctionne un empoisonnement de cache
#

Les caches GitHub Actions ne sont pas isolés par nom de workflow ou par job. Leur visibilité dépend notamment de la clé, de la version interne du cache et de la branche ou du tag. Plusieurs workflows d’un même dépôt peuvent donc partager une entrée dans une portée compatible.

Une branche peut restaurer les caches de sa propre portée et ceux de la branche par défaut. Une pull request peut aussi lire les caches de sa branche de base. Ce comportement est nécessaire pour accélérer les builds, mais il impose de considérer le contenu restauré comme une donnée externe au workflow courant.

Un scénario d’attaque réaliste comporte généralement quatre étapes :

  1. un acteur externe peut influencer un job, par exemple au moyen d’une pull request, d’un commentaire ou d’une donnée interpolée sans précaution dans un script ;
  2. ce job dispose d’un accès en écriture à une portée de cache qu’un autre workflow peut lire ;
  3. il enregistre des fichiers sous une clé exacte ou un préfixe que le workflow cible acceptera ;
  4. un job plus privilégié restaure ces fichiers puis les exécute ou les interprète avec des secrets, un jeton en écriture ou un accès au cloud.

Le risque n’est donc pas identique pour tous les chemins mis en cache. Un cache de téléchargements npm utilisé ensuite par npm ci avec un lockfile et des contrôles d’intégrité offre moins de possibilités directes qu’un répertoire node_modules, un environnement Python complet, un dossier de binaires ou des objets de compilation exécutés sans reconstruction. Il faut néanmoins garder la même frontière : le cache améliore les performances, il ne constitue pas une source de confiance.

Le cas le plus sensible concerne les événements qui s’exécutent dans le contexte de la branche par défaut tout en pouvant être déclenchés ou influencés par une personne sans droit d’écriture. pull_request_target, issue_comment et certaines cascades workflow_run en font partie. Une injection de commande ou un checkout imprudent de la tête d’une pull request peut alors donner du code exécutable à l’attaquant dans un contexte plus privilégié.

L’événement pull_request classique est un cas particulier. Les caches qu’il crée sont associés à la référence de fusion refs/pull/.../merge. Ils peuvent être relus par une nouvelle exécution de cette pull request, mais pas par la branche de base ou par une autre pull request. Lui imposer read reste utile pour appliquer une politique stable, réduire les écritures et empêcher un empoisonnement entre les nouvelles exécutions de la même PR, mais le risque pour le cache de main est déjà limité par cette portée.

Impact réel
#

La publication de cache-mode ne signifie pas que tous les dépôts GitHub étaient immédiatement exploitables avant le 10 septembre. Depuis juin 2026, GitHub limite déjà en lecture seule plusieurs déclencheurs peu fiables lorsqu’ils utilisent la portée de la branche par défaut. Un workflow qui n’a pas redonné explicitement l’écriture bénéficie de cette protection.

La priorité d’audit est élevée lorsqu’un dépôt réunit ces éléments :

  • des workflows pull_request_target, issue_comment ou workflow_run traitent des données externes ;
  • l’un de ces jobs déclare write ou write-only, ou appelle un workflow réutilisable capable de le faire ;
  • un workflow de publication, de déploiement ou de signature restaure des clés compatibles ;
  • le contenu restauré peut être exécuté avant ou pendant l’accès aux secrets.

Le risque est plus faible lorsque les seules écritures viennent de push sur une branche protégée, que les consommateurs n’ont pas de secret et que les clés incluent le hash du lockfile. Il n’est pas nul : un compte collaborateur compromis, une action tierce détournée ou une injection dans un workflow dit fiable peut encore produire une entrée malveillante.

Pour un dépôt qui n’utilise aucun cache, le changement n’impose rien. Pour un dépôt qui cache uniquement des téléchargements dans des jobs sans privilège, l’enjeu est surtout de formaliser la politique. L’urgence concerne les chemins où un cache relie un contexte influençable de l’extérieur à un contexte plus privilégié.

Ce que contrôle réellement cache-mode
#

La matrice est simple :

ModeRestaurerEnregistrerUsage courant
readOuiNonTests de PR et consommateurs du cache
writeOuiOuiBuild fiable qui réutilise et actualise son cache
write-onlyNonOuiProducteur dédié qui ne restaure pas de cache Actions
noneNonNonPublication, signature ou déploiement sans besoin de cache

Au niveau du workflow, la clé s’applique à tous les jobs :

permissions:
  contents: read

cache-mode: read

Un job peut ensuite définir sa propre valeur :

cache-mode: none

jobs:
  build-cache:
    runs-on: ubuntu-latest
    cache-mode: write-only
    steps:
      - run: echo "Ce job peut enregistrer un cache sans en restaurer"

L’application ne repose pas uniquement sur le bon comportement de actions/cache. Le runner obtient un jeton de cache limité et le service refuse l’opération qui dépasse le mode effectif. Les actions basées sur le toolkit @actions/cache respectent également ce mode.

Le runner expose la valeur réellement appliquée dans ACTIONS_CACHE_MODE. Pour lever un doute pendant une migration, un job peut afficher uniquement cette variable :

- name: Afficher le mode de cache effectif
  shell: bash
  run: printf 'ACTIONS_CACHE_MODE=%s\n' "$ACTIONS_CACHE_MODE"

Une opération interdite par le mode ne fait pas échouer le job. Une restauration refusée devient un cache miss et un enregistrement refusé est ignoré. L’action écrit un message d’information dans les logs, puis le workflow continue. Il faut en tenir compte lors des mesures de durée : un pipeline peut devenir plus lent sans passer en erreur.

Les valeurs par défaut
#

Si cache-mode est absent, GitHub conserve un comportement dépendant du déclencheur :

Contexte effectifMode par défaut
Déclencheur fiablewrite
Déclencheur peu fiable dans la portée de la branche par défautread

Pour la portée de la branche par défaut, les événements autorisés à écrire par défaut sont push, workflow_dispatch, repository_dispatch, delete, registry_package, page_build et schedule. Les autres événements résolus sur cette portée reçoivent normalement un accès en lecture seule.

Cette protection est en place depuis juin 2026. La nouveauté de septembre permet de rendre la politique explicite et de la réduire davantage. Elle permet aussi de la contourner : une déclaration cache-mode: write ou cache-mode: write-only prend le pas sur le défaut sécurisé, même avec un déclencheur peu fiable. GitHub ajoute une annotation, mais n’interdit pas l’exécution.

Il ne faut donc jamais utiliser write-only comme synonyme de « faible privilège ». Ce mode ne peut pas lire un cache, mais il peut précisément déposer le contenu qui sera consommé plus tard. Sur un job influencé par une contribution externe, cette capacité reste dangereuse.

Quelle politique choisir
#

Une politique raisonnable peut se résumer ainsi :

Type de jobMode conseilléRéserve
Validation d’une pull request externeread ou noneread accélère le job, mais le cache restauré reste non fiable
pull_request_target, issue_comment, workflow_runread par défaut, sinon noneNe jamais accorder l’écriture à un job qui traite une donnée contrôlée par l’appelant
Tests sur un push vers mainread si un producteur séparé existe, sinon writewrite doit rester réservé à du code et des entrées de confiance
Producteur de cache dédié sur mainwrite-onlyConstruire depuis le lockfile sans restaurer d’ancien cache
Publication, signature ou déploiementnone si possibleSi une lecture est indispensable, isoler le build du job qui reçoit les secrets
Appel d’un workflow réutilisableLimite explicite sur le job appelantNe pas dépendre du mode demandé par le workflow appelé

Le choix ne doit pas être basé uniquement sur le nom de l’événement. Un workflow_dispatch est classé parmi les déclencheurs autorisés à écrire par défaut, mais ses entrées peuvent encore devenir dangereuses si elles sont injectées directement dans une commande. De même, un push vers une branche protégée est fiable seulement si les règles de revue et les comptes autorisés le sont réellement.

Architecture recommandée : consommateurs en lecture, producteur séparé
#

La séparation la plus lisible utilise deux workflows. Le premier valide les pull requests sans pouvoir écrire dans le cache. Le second alimente le cache depuis main sans restaurer une entrée existante.

Workflow de pull request en lecture seule
#

Cet exemple demande le cache de téléchargement npm avec une clé incluant le hash du lockfile. Il ne restaure pas node_modules et n’utilise pas de restore-keys large.

name: Pull request checks

on:
  pull_request:

permissions:
  contents: read

cache-mode: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Setup Node.js
        uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          node-version: 24
          package-manager-cache: false

      - name: Restore npm cache
        uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-24-npm-${{ hashFiles('package-lock.json') }}

      - run: npm ci
      - run: npm test

L’action restore exprime l’intention sans ambiguïté. Le mode read ajoute la frontière côté service : même si une action ajoutée plus tard tente d’enregistrer un cache, elle n’obtiendra pas le droit nécessaire.

package-manager-cache: false est volontaire. setup-node v7 peut activer automatiquement la mise en cache npm si package.json déclare npm dans packageManager ou devEngines.packageManager. Sans ce réglage, une revue limitée aux étapes actions/cache peut manquer une opération implicite.

Producteur fiable en write-only
#

Le workflow suivant s’exécute uniquement après un push sur main. Il télécharge les dépendances sans script de cycle de vie, vérifie le cache npm local, puis enregistre l’entrée. Comme le job est en write-only, une ancienne entrée du cache GitHub Actions ne peut pas influencer sa construction.

name: Maintain npm cache

on:
  push:
    branches:
      - main
    paths:
      - package.json
      - package-lock.json
      - .github/workflows/cache-main.yml

permissions:
  contents: read

cache-mode: none

jobs:
  seed-npm-cache:
    runs-on: ubuntu-latest
    cache-mode: write-only
    steps:
      - name: Checkout
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Setup Node.js
        uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          node-version: 24
          package-manager-cache: false

      - name: Populate npm cache from the lockfile
        run: npm ci --ignore-scripts

      - name: Verify npm cache
        run: npm cache verify

      - name: Save npm cache
        uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-24-npm-${{ hashFiles('package-lock.json') }}

Ce modèle accepte un coût : une nouvelle version du lockfile n’aura pas de cache pour sa première validation en PR. C’est généralement préférable à un workflow qui autorise chaque contribution externe à produire une entrée partagée. Si le dépôt reçoit peu de contributions externes, le surcoût reste limité.

Un build fiable qui a besoin de restaurer une entrée précédente pour produire la suivante peut utiliser write. Il faut alors accepter que son point de départ dépend du contenu déjà stocké. Pour un cache de compilation complexe, une reconstruction périodique en write-only ou none permet de vérifier que le build ne dépend pas d’une restauration du cache Actions. Sur un runner auto-hébergé persistant, il faut également nettoyer ou recréer l’environnement de travail.

Job de publication sans cache
#

Un job qui reçoit un droit OIDC, un identifiant de registre ou un secret de signature ne devrait pas restaurer un cache par habitude. S’il n’en a pas besoin, coupez cet accès explicitement. Les étapes de publication sont volontairement omises dans cet extrait :

permissions:
  contents: read
  id-token: write

cache-mode: none

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          node-version: 24
          package-manager-cache: false
      # Restaurer ici un artefact préalablement vérifié, puis le publier.

Séparez la construction et la publication dès que le job de build exécute des dépendances ou des scripts. Le job de publication doit vérifier l’identité et la provenance de l’artefact reçu avant de lui accorder un contexte privilégié. Déplacer le fichier vers un artefact GitHub Actions sans vérification ne supprime pas la frontière de confiance.

Le cas des workflows réutilisables
#

Un workflow réutilisable peut cacher une opération de restauration ou d’enregistrement derrière une interface très simple. cache-mode est transmis depuis l’appelant et limite les droits que le workflow appelé peut demander.

jobs:
  shared-ci:
    permissions:
      contents: read
    cache-mode: read
    uses: example-org/ci/.github/workflows/node.yml@<sha-complet-vérifié>

Si le workflow appelé demande write alors que l’appelant a fixé read, GitHub refuse de démarrer l’exécution avec une erreur de validation. read et write-only ne sont pas ordonnés : le premier autorise uniquement la lecture, le second uniquement l’écriture. Un appelant en write-only ne peut donc pas appeler un workflow qui exige read.

Le point subtil concerne l’absence de valeur explicite. Si le job appelant ne définit ni n’hérite de cache-mode, un workflow appelé peut demander write, y compris lorsque le défaut du déclencheur appelant aurait été read. Pour un workflow tiers ou centralisé, fixez toujours la limite sur le job qui utilise uses:.

Vérifier son exposition
#

Commencez par inventorier les opérations explicites et les actions de setup susceptibles de gérer un cache :

rg -n \
  --glob '*.yml' \
  --glob '*.yaml' \
  '^[[:space:]]*(-[[:space:]]*)?(cache-mode:|cache:|package-manager-cache:|uses:.*(actions/cache|actions/setup-(node|python|java|go|dotnet)|ruby/setup-ruby))' \
  .github/workflows

Recherchez ensuite les déclencheurs qui demandent une revue attentive :

rg -n \
  --glob '*.yml' \
  --glob '*.yaml' \
  '\b(pull_request_target|issue_comment|workflow_run|pull_request|workflow_dispatch|repository_dispatch|schedule|push)\b' \
  .github/workflows

Ces commandes constituent un inventaire, pas une preuve d’absence. Elles ne développent pas les workflows réutilisables et ne détectent pas nécessairement une action tierce qui utilise directement le toolkit de cache. Pour chaque uses: externe, contrôlez la documentation et le code de la version réellement épinglée.

La revue doit répondre à quelques questions concrètes :

  • quel événement déclenche le job ?
  • qui peut contrôler son payload, ses inputs ou le code checkouté ?
  • quelle portée de cache reçoit-il réellement ?
  • peut-il écrire, directement ou via une action de setup ?
  • quels autres workflows restaurent la même clé ou un restore-keys compatible ?
  • les fichiers restaurés sont-ils ensuite exécutés ?
  • le job consommateur possède-t-il des secrets ou des permissions en écriture ?

Évitez les clés trop génériques dans les workflows privilégiés. Une clé incluant le système, la version du runtime et le hash du lockfile réduit les collisions accidentelles :

key: ${{ runner.os }}-node-24-npm-${{ hashFiles('package-lock.json') }}

Un restore-keys comme npm- accepte la dernière entrée portant ce préfixe lorsqu’aucune clé exacte ne correspond. C’est pratique pour les performances, mais la surface de sélection devient plus large. Sur un job de publication ou de signature, évitez ces préfixes larges et désactivez le cache s’il n’est pas indispensable.

Même sans restore-keys, l’action peut rechercher une correspondance par préfixe de key si la clé exacte est absente. Inclure le hash du lockfile resserre la sélection sans garantir une correspondance strictement exacte. La sortie cache-hit: 'true' indique une correspondance exacte, mais ne prouve pas l’authenticité du contenu restauré.

Détection et réponse à incident
#

L’interface Actions > Caches affiche les clés, les références, la taille, la date de création et le dernier accès. La CLI permet d’obtenir le même inventaire sans modifier le dépôt :

gh cache list \
  --limit 100 \
  --sort created_at \
  --order desc \
  --json id,key,ref,sizeInBytes,createdAt,lastAccessedAt

Pour se concentrer sur la branche par défaut :

gh cache list \
  --ref refs/heads/main \
  --limit 100 \
  --json id,key,ref,sizeInBytes,createdAt,lastAccessedAt

Ces métadonnées ne donnent pas une provenance cryptographique du contenu. Une création à une heure inhabituelle, une taille qui change fortement ou une clé inattendue justifie une corrélation avec les exécutions Actions, mais ne prouve pas à elle seule un empoisonnement.

Dans les logs, recherchez aussi :

  • une annotation signalant write ou write-only sur un déclencheur peu fiable ;
  • une sauvegarde provenant d’un job pull_request_target, issue_comment ou workflow_run ;
  • une restauration par préfixe alors qu’une clé exacte était attendue ;
  • un cache miss soudain suivi d’une création depuis un contexte inhabituel ;
  • des commandes, connexions sortantes ou modifications du dépôt inexpliquées après la restauration.

Si une entrée semble compromise, empêchez d’abord les workflows privilégiés de la restaurer en passant temporairement leur mode à none. Identifiez ensuite précisément l’entrée avant suppression. La commande suivante supprime le cache distant ciblé et n’est pas réversible. Remplacez CACHE_ID par son identifiant numérique et OWNER/REPO par le dépôt concerné :

gh cache delete CACHE_ID --repo OWNER/REPO

Après suppression, reconstruisez le cache avec un producteur fiable en write-only. La suppression ne revient pas sur les jobs déjà exécutés. Si un workflow privilégié a restauré puis utilisé l’entrée suspecte :

  1. examinez les logs du job et les journaux des services auxquels il avait accès ;
  2. révoquez les secrets persistants présents dans son environnement ;
  3. contrôlez les modifications réalisées avec le GITHUB_TOKEN, dans les registres et dans le cloud ;
  4. reconstruisez un runner auto-hébergé persistant si du code arbitraire a pu s’y exécuter ;
  5. relancez les builds et publications depuis une révision connue après assainissement.

Ce que cache-mode ne protège pas
#

Le nouveau réglage ferme une capacité précise. Il ne doit pas devenir une justification pour relâcher les autres contrôles.

Il ne valide pas un cache restauré
#

read signifie uniquement que le job courant ne peut pas enregistrer une entrée. Il peut toujours recevoir un cache malveillant produit auparavant par un autre job autorisé à écrire. Les caches GitHub ne sont ni signés ni vérifiés avant extraction.

Il ne protège pas les secrets stockés dans le cache
#

Une pull request peut restaurer les caches visibles depuis sa branche de base. Ne placez jamais de jeton, fichier de configuration authentifié, clé privée ou identifiant de registre dans un chemin mis en cache. Passer ensuite le workflow en none ne retire pas les entrées déjà stockées.

Il ne remplace pas permissions
#

permissions limite le GITHUB_TOKEN. cache-mode limite le jeton du service de cache. Un job devrait généralement définir les deux :

permissions:
  contents: read

cache-mode: read

Les secrets, droits OIDC, environnements protégés et jetons fournis manuellement gardent leurs propres règles.

Il ne couvre pas tous les stockages intermédiaires
#

Le réglage vise le cache GitHub Actions et les clients qui utilisent son jeton limité. Il ne contrôle pas :

  • un cache S3 ou Redis configuré par l’application ;
  • un cache Docker exporté vers un registre OCI ;
  • les fichiers laissés sur le disque d’un runner auto-hébergé persistant ;
  • les artefacts transmis entre jobs ou workflows ;
  • un proxy de paquets interne.

Chacun de ces canaux nécessite sa propre politique d’écriture, de lecture et d’intégrité.

Il ne sécurise pas pull_request_target
#

Ce déclencheur reste dangereux si le workflow checkout la tête de la pull request puis l’exécute avec des secrets ou un jeton privilégié. cache-mode: read retire une voie d’écriture vers le cache, pas l’exécution de code ni les injections de commandes dans les expressions GitHub.

Plan de migration
#

Pour un dépôt existant, la migration peut rester progressive :

  1. inventorier actions/cache, les options cache: des actions de setup et les workflows réutilisables ;
  2. ajouter un cache-mode explicite au niveau de chaque workflow ;
  3. choisir read ou none pour les jobs déclenchés par des données externes ;
  4. concentrer les écritures dans un nombre réduit de jobs déclenchés depuis des branches protégées ;
  5. utiliser write-only pour les producteurs capables de repartir sans cache ;
  6. désactiver le cache dans les jobs qui publient, signent ou déploient lorsqu’il n’est pas indispensable ;
  7. resserrer les clés et supprimer les restore-keys trop larges des chemins privilégiés ;
  8. contrôler ACTIONS_CACHE_MODE et les logs sur quelques exécutions avant de comparer les temps de build ;
  9. documenter la suppression des caches et la rotation des secrets dans la procédure d’incident.

Le premier changement rentable consiste souvent à placer cache-mode: read sur tous les workflows de validation, puis à accorder write ou write-only uniquement aux producteurs identifiés. Cette approche rend les exceptions visibles pendant la revue de code.

Conclusion
#

cache-mode donne au cache GitHub Actions le contrôle de moindre privilège qui lui manquait au niveau du workflow et du job. La valeur par défaut protège déjà plusieurs déclencheurs peu fiables, mais une déclaration explicite évite de dépendre d’une classification implicite et limite aussi les workflows réutilisables.

Le modèle le plus défendable reste simple : des consommateurs en read, un petit nombre de producteurs fiables en write ou write-only, et none dès que le gain de performance ne justifie pas l’exposition. Il faut surtout retenir que write-only est un droit d’écriture complet et que read ne certifie jamais le contenu restauré.

Pour un dépôt qui utilise pull_request_target, issue_comment ou workflow_run, la priorité est de rechercher toute déclaration write ou write-only. Sur ces événements, l’annotation GitHub ne remplace pas une correction : sauf cas très encadré, le cache doit rester en lecture seule et être alimenté par un workflow de confiance.

Sources
#

Sources vérifiées le 15 septembre 2026 :

Articles connexes

Attaques supply chain : ce que Trivy, XZ et Polyfill.io changent pour vos déploiements

··1736 mots·9 mins
Le 19 mars 2026, un acteur disposant d’identifiants compromis a publié une version malveillante de Trivy et détourné les références de ses actions GitHub. Trivy est justement utilisé pour détecter des vulnérabilités dans les dépendances et les images de conteneurs. L’incident ne rend pas le scanner inutile. Il rappelle qu’un outil de sécurité reste un logiciel distribué par une chaîne de build, des comptes, des registres et des mécanismes de mise à jour qui peuvent eux-mêmes être compromis. Mise à jour du 28 août 2026 : cet article a été recentré sur les faits confirmés par les projets concernés. Plusieurs exemples historiques de la version initiale mélangeaient des dates ou des mécanismes d’attaque différents. Les commandes ont aussi été adaptées aux versions actuelles des outils cités.

Nginx RIFT (CVE-2026-42945) : vérifier les configurations réellement exposées

··1298 mots·7 mins
CVE-2026-42945, surnommée Nginx RIFT par ses découvreurs, est un dépassement de tampon dans ngx_http_rewrite_module. Le défaut existe depuis Nginx 0.6.27 et peut être déclenché à distance lorsqu’une configuration utilise une séquence particulière de directives rewrite et set avec des données contrôlées par le client. L’équipe de recherche depthfirst a démontré une exécution de code avec l’ASLR désactivé. Cette preuve établit que la corruption mémoire est exploitable dans un environnement préparé, mais elle ne démontre pas une exécution de code fiable sur toute installation Nginx moderne. Nginx classe la vulnérabilité au niveau medium. Les versions 0.6.27 à 1.30.0 sont affectées. Les branches 1.30.1 et 1.31.0 ont introduit le correctif. Mise à jour du 28 août 2026 : la première version de cet article évaluait trop largement le risque comme élevé pour les reverse proxies, homelabs et ingress Kubernetes. La priorité dépend d’abord de la version et de la présence du chemin rewrite/set vulnérable. La qualification amont est medium.

Dirty Frag sous Linux : vérifier l'exposition et installer les correctifs

··1359 mots·7 mins
Dirty Frag désigne deux vulnérabilités du noyau Linux publiées le 7 mai 2026 par Hyunwoo Kim. Elles sont suivies sous CVE-2026-43284 pour le chemin XFRM/ESP et CVE-2026-43500 pour RxRPC. Dans les deux cas, un attaquant qui peut déjà exécuter du code localement peut modifier une page du cache mémoire associée à un fichier normalement accessible en lecture seule. Le démonstrateur public utilise cette primitive pour obtenir les privilèges root. Mise à jour du 28 août 2026 : les deux CVE disposent désormais de correctifs dans les noyaux fournis par les principales distributions. La désactivation des modules reste une solution temporaire lorsque la mise à jour est impossible. L’article initial, écrit pendant la divulgation, indiquait encore que le second correctif n’était pas publié.