EN
en direct

Kubernetes 1.37 verrouille enfin les volumes avec noexec, nosuid et un mode sur emptyDir

La version 1.37 de Kubernetes introduit deux réglages de sécurité du stockage, encore en alpha : des options de montage bind (noexec, nosuid, nodev) et un mode de permission sur les volumes emptyDir. Activez les feature gates VolumeBindMountOptions et EmptyDirVolumeMode pour remplacer les contournements par conteneur d’initialisation.

Une rangée de portes de cage de stockage métalliques entrouvertes, un seul cadenas ambre suspendu à l’un des loquets.

16 septembre 2026. Kubernetes v1.37 documente deux nouveautés de durcissement du stockage, toutes deux en alpha : les options de montage bind (noexec, nosuid, nodev) et un mode de permission sur les volumes emptyDir. 16 septembre. Les ingénieurs de Red Hat qui portent la fonction détaillent le « pourquoi » dans un billet du blog officiel. 20 septembre. Aucun cluster ne les applique encore par défaut : il faut activer deux feature gates. Pourquoi c’est important : depuis toujours, un processus compromis dans un conteneur peut exécuter un binaire depuis n’importe quel volume inscriptible — même avec un système de fichiers racine en lecture seule — faute de drapeau noexec posé par défaut.

Le trou que ces deux réglages comblent

Le point de départ est un détail du kubelet et des runtimes de conteneurs que peu d’équipes mesurent : quand un volume est monté en bind mount dans un conteneur, il l’est sans les drapeaux noexec, nosuid ni nodev. Autrement dit, tout volume inscriptible — un emptyDir, un PersistentVolume, un montage hostPath — est monté avec la permission d’exécuter ce qui s’y trouve.

La conséquence est directe. Un attaquant qui a obtenu une exécution de code dans un conteneur, même avec readOnlyRootFilesystem: true, peut télécharger un binaire dans le volume inscriptible, le rendre exécutable avec chmod +x, puis le lancer. Le système de fichiers racine est verrouillé, mais le volume ne l’est pas : la protection contournée devient un exercice de confort. La faille a été documentée depuis longtemps — l’audit de sécurité Kubernetes 1.24 (NCC-E003660-7HM) pointait déjà l’impossibilité de monter un emptyDir avec noexec comme un échec de sécurité, et l’issue #48912 traînait depuis des années.

Le second trou concerne les permissions des volumes emptyDir. Par défaut, un emptyDir est créé avec un mode 0777 codé en dur : n’importe quel processus qui découvre le volume peut lire, écrire et supprimer tout ce qu’il contient, quel que soit son propriétaire. La parade existante — un conteneur d’initialisation qui exécute un chmod — fonctionne, mais elle ajoute de la complexité, elle est difficile à auditer pour la conformité, et elle ne règle pas le cas du sticky bit (mode 01777), attendu sur tout répertoire partagé digne de /tmp, ni celui des permissions restreintes comme 0750.

Deux portes d’entrée, deux leviers

La 1.37 répond aux deux problèmes par deux mécanismes distincts et complémentaires.

Le premier, bindMountOptions, s’ajoute à la spécification d’un volumeMount. Il accepte exactement les trois drapeaux du VFS Linux que l’on attend d’un montage durci : noexec (interdit l’exécution de binaires), nosuid (neutralise les bits setuid/setgid) et nodev (ignore les fichiers spéciaux de type périphérique). C’est la réponse native à l’exigence des référentiels de durcissement — CIS, NSA/CISA, PCI-DSS — qui réclament précisément ces drapeaux sur les montages inscriptibles.

Le second, mode, s’ajoute au volume source emptyDir. Il permet de fixer la permission de création du répertoire : 01777 pour un espace de travail partagé qui se comporte comme /tmp, 0750 pour un répertoire restreint au propriétaire et à son groupe. Le sticky bit de 01777 change la donne dans les pods multi-conteneurs : un processus compromis dans un conteneur ne peut plus supprimer les artefacts produits par un autre conteneur du même pod, car seul le propriétaire d’un fichier (ou root) peut le supprimer.

Les deux fonctionnalités sont indépendantes et peuvent se combiner sur le même montage — par exemple un emptyDir partagé, monté en noexec,nosuid, avec un mode 01777.

Comment l’activer dès aujourd’hui

Les deux réglages sont derrière des feature gates alpha : VolumeBindMountOptions et EmptyDirVolumeMode, à activer sur l’API server et le kubelet. En 1.37, ils ne sont pas actifs par défaut, et leur statut alpha impose la prudence : la syntaxe peut évoluer, et il faut les valider sur un cluster de test avant de généraliser.

Le manifeste minimal pour monter un emptyDir en /tmp avec les drapeaux de durcissement :

yaml
apiVersion: v1
kind: Pod
metadata:
  name: hardened-bindmount-pod
spec:
  os:
    name: linux
  containers:
    - name: hardened-app
      image: alpine:latest
      command: ["sleep", "3600"]
      securityContext:
        readOnlyRootFilesystem: true
      volumeMounts:
        - name: temp-storage
          mountPath: /tmp
          bindMountOptions:
            - noexec
            - nosuid
  volumes:
    - name: temp-storage
      emptyDir: {}

Et la variante qui impose un sticky bit sur un répertoire partagé, en forçant le mode de création :

yaml
apiVersion: v1
kind: Pod
metadata:
  name: sticky-tmp-pod
spec:
  containers:
    - name: app
      image: alpine:latest
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir:
        mode: "01777"

Le second manifeste remplace le conteneur d’initialisation qui exécutait chmod 1777 /tmp avant le démarrage de l’application : une ligne déclarative à la place d’un sidecar de contournement.

Ce que ça change concrètement

Les cas d’usage exposés par les auteurs sont précis, et ils parlent directement à une équipe plateforme.

  • Empêcher l’escalade sur les montages inscriptibles. Un espace de travail temporaire monté en noexec,nosuid garantit que, même si l’application est compromise et qu’une charge est téléchargée, la charge ne peut ni s’exécuter ni exploiter un bit setuid pour escalader sur le nœud.
  • Sécuriser l’espace partagé des pods multi-conteneurs. Un pod de CI/CD avec un conteneur de build et un sidecar de log peut partager un volume en mode 01777 : chacun écrit librement, mais un processus compromis ne peut plus détruire les artefacts du voisin.
  • Appliquer le moindre privilège aux données. Une base de données dont le stockage temporaire est monté en 0750 n’est lisible que par l’utilisateur et le groupe attendus, refusant l’accès à tout autre sidecar du pod.

Le point commun des trois scénarios : la sécurité se déclare dans le manifeste, pas dans un script d’initialisation. C’est exactement la direction que la communauté suit depuis plusieurs versions — penser la posture de sécurité comme une configuration auditable et reproductible, pas comme une série de rustines au démarrage.

Déployer des gates alpha sans casser le nœud

Comme les deux fonctionnalités sont en alpha, quelques détails opérationnels comptent avant de basculer. Les gates doivent être activées sur le kubelet et l’API server, ce qui impose un redémarrage roulant du plan de contrôle et du parc de nœuds — à planifier plutôt qu’à découvrir en cours de route. Les volumes existants ne sont pas affectés : les nouveaux champs ne s’appliquent qu’aux pods que vous annotez explicitement avec bindMountOptions ou un emptyDir.mode, donc activer les gates ne change pas le comportement des charges que vous laissez en l’état.

Le vrai travail est la vérification. Un pod qui ignore silencieusement la demande noexec serait pire qu’un pod qui ne l’a jamais formulée : confirmez donc que les drapeaux atteignent bien le runtime, par exemple en tentant d’exécuter un binaire depuis le volume monté dans un pod de test et en attendant l’échec. Et comme certains pilotes CSI et runtimes de conteneurs traduisent les options de montage de façon incohérente, testez contre le pilote et le runtime exacts que vous utilisez en production avant de migrer quoi que ce soit de sensible.

Verdict

Si vous exploitez des clusters multi-tenant, des pods de CI/CD ou des charges soumises à un référentiel de durcissement, activez VolumeBindMountOptions et EmptyDirVolumeMode sur un cluster de test dès la 1.37, et commencez à migrer vos montages inscriptibles vers noexec,nosuid avec un mode explicite — c’est le moyen le plus propre de fermer un trou d’exécution que la plupart des clusters laissent ouvert depuis toujours. Si vous restez en 1.36 ou avant, le contournement par conteneur d’initialisation avec chmod et un securityContext correct reste la seule voie, mais documentez-le : la conformité se prouve, elle ne se devine pas. Si vous ne faites ni l’un ni l’autre, au minimum posez noexec au niveau du nœud sur les répertoires de volumes et ajoutez le montage readOnlyRootFilesystem — une posture partielle vaut toujours mieux qu’un volume inscriptible exécutable par défaut.

Références

Le brief cyber, chaque mardi

Les failles qui comptent, les correctifs à appliquer, en dix minutes de lecture.

Pas de spam. Désinscription en un clic.
à lire ensuite

Sur le même sujet

Un backup Kubernetes n’est pas une reprise après sinistre

Le 10 septembre 2026, deux ambassadeurs CNCF ont publié trois scénarios de panne reproductibles qui séparent le fait d’avoir des sauvegardes de celui de pouvoir réellement restaurer. Testez la restauration complète dans un cluster qui n’a jamais tourné, validez les données contre un résultat attendu et chronométrez le tout.

← Retour au fil

Tapez au moins deux caractères.

naviguer ouvrir esc fermer