Checkmk RCE : trois failles critiques dans un seul correctif (CVE-2026-121374)
Trois failles Checkmk permettent à un éditeur de règles, à un site distant malveillant ou à un hôte compromis d'exécuter du code ; corrigées en 2.5.0p19.
En bref
- Checkmk 2.5.0p19 et 2.4.0p40 corrigent trois failles critiques qui aboutissent chacune à l'exécution de code en tant qu'utilisateur du site. L'éditeur a publié les deux correctifs le 11 novembre 2026.
- Tout site antérieur à 2.5.0p19 sur la branche 2.5, ou à 2.4.0p40 sur la branche 2.4, est concerné. La version 2.3.0 est en fin de vie et ne reçoit aucun correctif.
- Les trois failles sont notées CVSS v4.0 9,4 Critique. Aucune preuve de concept publique ni exploitation dans la nature n'est connue, et aucune ne figure dans le catalogue KEV de la CISA au 11 novembre 2026.
- Mettez à niveau vers 2.5.0p19 ou 2.4.0p40. Si vous ne pouvez pas, restreignez l'édition des règles et ne connectez pas le site central à des sites distants non fiables ; voir « Comment corriger ? » pour les limites.
Suis-je concerné ?
Le critère de version s'applique à toutes les failles ; les autres conditions s'appliquent séparément aux CVE indiqués :
- Vous exploitez un site Checkmk en 2.5.0 avant 2.5.0p19, ou en 2.4.0 avant 2.4.0p40. La version 2.3.0 est concernée et en fin de vie.
- Pour CVE-2026-121374, au moins un utilisateur peut modifier des règles dans au moins un dossier. Par défaut, cela inclut le rôle « Normal monitoring user » lorsqu'il possède des permissions sur un dossier.
- Pour CVE-2026-118965, votre site central synchronise les étiquettes d'hôtes découvertes depuis des sites distants que vous ne considérez pas comme entièrement fiables.
- Pour CVE-2026-120495, vous utilisez l'édition Pro, Ultimate, Cloud ou Ultimate MT avec la supervision synthétique Robotmk, et un hôte surveillé peut envoyer des données d'agent forgées.
La première faille ne nécessite pas Kubernetes. Un utilisateur qui peut créer une règle peut ajouter une règle d'agent spécial Kubernetes même si le site ne surveille aucun cluster. La troisième faille exige la découverte automatique des services pour l'hôte, ou qu'un administrateur de supervision confirme les services Robotmk à la main.
| Branche | Versions concernées | Version corrigée |
|---|---|---|
| 2.5 | 2.5.0 à 2.5.0p18 | 2.5.0p19, publiée le 2026-11-11 |
| 2.4 | 2.4.0 à 2.4.0p39 | 2.4.0p40, publiée le 2026-11-11 |
| 2.3 | toutes les versions 2.3.0 | Aucune ; fin de vie |
| 3.0 | 3.0.0b1 | Pas encore publiée ; contient les correctifs |
Vérifiez la version sur chaque site, y compris les sites distants :
omd version
Dans un site, le cœur de supervision rapporte la même version :
sudo -u <site> cmk --version
L'interface web l'affiche sous Help > About. La commande omd sites liste les noms de sites lorsque vous ne savez pas lesquels existent.
Comment corriger ?
Installez le paquet 2.5.0p19 ou 2.4.0p40 correspondant à votre édition et à votre distribution, puis mettez à jour chaque site. Les pages werk de l'éditeur indiquent que la version est compatible, sans interaction manuelle après la mise à jour.
- Installez le paquet correspondant à votre édition, par exemple
check-mk-raw-2.5.0p19,check-mk-enterprise-2.5.0p19ou le paquet 2.4.0p40 équivalent. - Mettez à jour chaque site, y compris les sites distants :
omd update <site> - Sur une appliance Checkmk, importez l'image 2.5.0p19 ou 2.4.0p40 dans l'interface de l'appliance et lancez la mise à jour depuis celle-ci.
- Confirmez le résultat :
omd version - Répétez sur chaque site distribué. La faille des étiquettes d'hôtes est corrigée sur le site central ; les failles Kubernetes et Robotmk sont corrigées sur le site qui exécute ces contrôles.
Si vous ne pouvez pas mettre à jour immédiatement, réduisez l'exposition avec ces mesures. Chacune limite un chemin d'attaque, et aucune ne remplace le correctif.
- Retirez la permission « Edit rules » de tous les rôles non administratifs, et vérifiez à quels dossiers ces rôles ont accès. Un administrateur peut encore exploiter CVE-2026-121374 ; cette mesure supprime seulement le chemin par défaut des utilisateurs de supervision ordinaires.
- Ne connectez pas un site central à des sites distants que vous ne contrôlez pas. CVE-2026-118965 n'a pas d'interrupteur de configuration ; le correctif est la mise à jour.
- Traitez les hôtes surveillés comme non fiables pour CVE-2026-120495. Restreignez les personnes qui peuvent ajouter des services et désactivez la découverte automatique des services pour les hôtes que vous n'administrez pas. Un hôte qui peut envoyer des données d'agent atteint encore la faille lorsqu'un administrateur ajoute ses services.
- Migrez tout site 2.3.0 vers 2.4.0p40 ou 2.5.0p19. La branche 2.3.0 est en fin de vie et n'a aucune version corrigée.
Quelle est la cause racine ?
Les trois failles partagent un même schéma. Une valeur contrôlée par une partie moins privilégiée atteint une ligne de commande ou un chemin de fichier sans confinement. Les privilèges de l'utilisateur du site transforment alors l'écriture en exécution de code. Chaque point d'entrée est différent, donc chaque correctif l'est aussi.
La première faille se trouve dans l'agent spécial Kubernetes. L'option de règle « Cluster resource aggregation > Exclude nodes based on their role » collecte des noms de rôles. L'appel côté serveur transmet ces noms à l'agent comme arguments séparés après une seule option :
match params.cluster_resource_aggregation:
case ("cluster_aggregation_exclude_node_roles", list(excluded_roles)):
args.append("--cluster-aggregation-exclude-node-roles")
args.extend(excluded_roles)
L'agent analyse ses arguments avec argparse. Le parseur vulnérable déclarait l'option avec nargs="+", donc il consommait tous les jetons suivants qui ne ressemblaient pas à une option :
group.add_argument(
"--cluster-aggregation-exclude-node-roles",
nargs="+",
default=["control-plane", "infra"],
dest="roles",
)
Une valeur de rôle qui commence par --profile n'est pas une valeur pour argparse. C'est une nouvelle option, et la valeur de rôle suivante devient son argument. L'option --profile écrit des données de profilage dans un fichier et, dans le même dossier, un lanceur Python exécutable dont le source contient le chemin du profil :
f'stats = pstats.Stats("{self._profile_file}")\n'
Un chemin contenant un guillemet double et de la syntaxe Python modifie donc le source du lanceur. Selon l'évaluation du werk, un éditeur de règles peut écrire un script Python exécutable au contenu contrôlé et atteindre l'exécution de code en tant qu'utilisateur du site.
La deuxième faille se trouve dans la synchronisation des étiquettes d'hôtes. Le site central demande à chaque site distant les étiquettes d'hôtes découvertes de ses hôtes, puis écrit le contenu renvoyé sur disque. Le code vulnérable concaténait le nom de fichier fourni par le site distant au dossier des étiquettes sans aucune vérification :
def save_updated_host_label_files(updated_host_labels: list[UpdatedHostLabelsEntry]) -> None:
for file_name, mtime, content in updated_host_labels:
file_path = cmk.utils.paths.discovered_host_labels_dir / file_name
store.save_text_to_file(file_path, content)
os.utime(file_path, (mtime, mtime))
Un nom de fichier contenant ../ sort du dossier, et un nom terminé par un autre suffixe écrit un fichier que le site importe ou exécute ensuite. Un site distant compromis écrit donc des fichiers arbitraires sur le site central.
La troisième faille se trouve dans le service de test Robotmk. Le service prend un nom de cas de test dans les données de l'agent et l'utilise pour créer le dossier du journal HTML. Le chemin final n'était pas validé, donc un nom de cas forgé sort du dossier des journaux. Le contenu du journal est aussi défini par l'utilisateur, ce qui transforme l'écriture en exécution de code selon l'évaluation de l'éditeur.
Comment la faille est-elle exploitée ?
Chaque faille exige une position de départ différente. Aucune ne nécessite une vulnérabilité dans l'hôte surveillé, sauf la troisième, qui exige un hôte capable d'envoyer des données d'agent.
Pour CVE-2026-121374 :
- Un utilisateur qui peut modifier des règles crée ou modifie une règle d'agent spécial Kubernetes.
- Dans « Exclude nodes based on their role », l'utilisateur saisit
--profilecomme rôle et un chemin comme valeur suivante. - Lorsque l'agent spécial s'exécute,
argparselit--profilecomme une option et le chemin comme son argument. - L'agent écrit les données de profilage et le script lanceur au chemin choisi. Le lanceur contient le chemin dans une chaîne Python.
- Un chemin forgé avec un guillemet et du code Python modifie le source du lanceur. L'éditeur considère le script exécutable obtenu comme une exécution de code en tant qu'utilisateur du site.
Pour CVE-2026-118965 :
- Un attaquant contrôle un site distant dans une installation distribuée, ou le compromet.
- Le site distant répond à la demande d'étiquettes du site central avec un nom de fichier qui contient
../. - La synchronisation du site central écrit le contenu fourni au chemin résolu.
- L'attaquant choisit un chemin que l'utilisateur du site importe ou exécute, ce qui donne l'exécution de code sur le site central.
Pour CVE-2026-120495 :
- Un attaquant peut ajouter des données d'agent pour un hôte surveillé, par exemple via un plug-in d'agent ou un fichier spool malveillant. Le werk indique que cela exige généralement les droits root sur l'hôte surveillé.
- Les données forgées définissent un nom de cas de test Robotmk qui sort du dossier des journaux HTML.
- Le site écrit un journal HTML au contenu contrôlé par l'attaquant au chemin résolu.
- L'éditeur évalue le résultat comme une exécution de code en tant qu'utilisateur du site.
Comment se déroule l'attaque ?
Trois entrées différentes aboutissent au même résultat : un fichier écrit en tant qu'utilisateur du site Checkmk, que l'éditeur considère comme une exécution de code.
un rôle de nœud exclu"] --> B["Le rôle est lu comme
une option --profile"] C["Un site distant malveillant
renvoie un nom de fichier d'étiquette"] --> D["Le nom est concaténé au
dossier des étiquettes
sans vérification du chemin"] E["Un hôte compromis envoie
un nom de test Robotmk"] --> F["Le nom devient le
dossier du journal
sans vérification du chemin"] B --> G["Fichier écrit en tant
qu'utilisateur du site"] D --> G F --> G G --> H["Exécution de code en tant
qu'utilisateur du site"] style D fill:#f8d7da style F fill:#f8d7da
Que peut faire un attaquant ?
Un attaquant qui atteint l'exécution de code lance des commandes en tant qu'utilisateur du site Checkmk. Ce compte lit la configuration de supervision, les identifiants que Checkmk utilise pour joindre les équipements surveillés et les fichiers du site. Les conditions varient selon la faille.
- CVE-2026-121374 : l'attaquant a besoin d'un utilisateur qui peut modifier des règles dans au moins un dossier. Le site n'a pas besoin de surveiller Kubernetes, car l'attaquant crée la règle. Le résultat est l'exécution de code en tant qu'utilisateur du site.
- CVE-2026-118965 : l'attaquant a besoin de contrôler un site distant dans une installation distribuée. Le résultat est une écriture arbitraire de fichiers sur le site central et l'exécution de code en tant qu'utilisateur du site central.
- CVE-2026-120495 : l'attaquant doit fournir des données d'agent forgées pour un hôte surveillé, ce qui, selon le werk, exige généralement les droits root sur cet hôte, et la découverte automatique des services ou un administrateur qui ajoute les services Robotmk. Le résultat est l'exécution de code en tant qu'utilisateur du site.
L'utilisateur du site n'est pas root sur le serveur Checkmk. Il peut néanmoins lire les données de supervision et les identifiants stockés pour les systèmes surveillés, donc traitez une compromission comme une exposition de ces systèmes également.
Pourquoi le correctif fonctionne-t-il ?
Les correctifs suppriment l'ambiguïté entre une valeur et une option, et confinent les chemins que le site écrit.
Le correctif Kubernetes transmet chaque rôle comme une option distincte avec une valeur attachée, et le parseur les ajoute une par une :
match params.cluster_resource_aggregation:
case None:
- args.extend(["--cluster-aggregation-exclude-node-roles", "control-plane", "infra"])
+ args.extend(
+ f"--cluster-aggregation-exclude-node-role={role}"
+ for role in ("control-plane", "infra")
+ )
case ("cluster_aggregation_include_all_nodes", None):
args.append("--cluster-aggregation-include-all-nodes")
case ("cluster_aggregation_exclude_node_roles", list(excluded_roles)):
- args.append("--cluster-aggregation-exclude-node-roles")
- args.extend(excluded_roles)
+ args.extend(
+ f"--cluster-aggregation-exclude-node-role={role}" for role in excluded_roles
+ )
group.add_argument(
- "--cluster-aggregation-exclude-node-roles",
- nargs="+",
- default=["control-plane", "infra"],
+ "--cluster-aggregation-exclude-node-role",
+ action="append",
+ default=None,
dest="roles",
+ metavar="ROLE",
)
Un rôle fait désormais partie du jeton --cluster-aggregation-exclude-node-role=<role>, donc argparse ne peut plus le lire comme une option séparée. L'agent restreint aussi --profile à ~/tmp/check_mk/debug et écrit le chemin dans le lanceur comme un littéral Python :
+def _profile_file(filename: str) -> Path:
+ path = Path(filename).resolve()
+ allowed = (Path.home() / _PROFILE_DIR).resolve()
+ if not path.is_relative_to(allowed):
+ raise argparse.ArgumentTypeError(f"Profiles can only be stored in {allowed}")
+ return path
- f'stats = pstats.Stats("{self._profile_file}")\n'
+ f"stats = pstats.Stats({str(self._profile_file)!r})\n"
Le correctif des étiquettes d'hôtes résout la cible et exige qu'elle reste sous le dossier des étiquettes, porte le suffixe .mk et utilise un nom d'hôte valide comme racine :
+def _make_secure_path(base: Path, leaf: str) -> Path:
+ path = Path(base).resolve()
+ resolved = (path / leaf).resolve()
+ if not resolved.is_relative_to(path):
+ raise ValueError(f"Path {resolved} is not relative to {path}")
+ if resolved.suffix != ".mk":
+ raise ValueError(f"Path {resolved} does not have .mk suffix")
+ HostName(resolved.stem) # would raise if validation fails
+ return resolved
+
+
def save_updated_host_label_files(updated_host_labels: list[UpdatedHostLabelsEntry]) -> None:
for file_name, mtime, content in updated_host_labels:
- file_path = cmk.utils.paths.discovered_host_labels_dir / file_name
+ file_path = _make_secure_path(cmk.utils.paths.discovered_host_labels_dir, file_name)
Le changement Robotmk confine les journaux générés à ~/var/robotmk/html_logs et renvoie un état de service UNKNOWN lorsqu'un journal sortirait de ce dossier. Le changement Robotmk est livré dans la même version corrective, et son werk est le document public de la nouvelle règle de chemin.
Comment vérifier si j'ai été compromis ?
Checkmk ne publie aucun indicateur de compromission pour ces failles. Une tentative qui échoue, ou qui écrit un fichier que le site n'exécute jamais, peut ne laisser aucune trace au-delà du fichier lui-même. Examinez les trois endroits que les failles touchent.
- Consultez le journal d'audit pour les changements de règles qui ajoutent une règle d'agent spécial Kubernetes ou modifient « Exclude nodes based on their role ». Dans l'interface web, ouvrez Setup > General > Audit log et filtrez sur le jeu de règles Kubernetes.
- Cherchez des fichiers inattendus dans le dossier de débogage du site :
sudo -u <site> find ~/tmp/check_mk/debug -type f -name '*.py' 2>/dev/null - Listez les fichiers d'étiquettes d'hôtes découverts et vérifiez que chaque nom correspond à un hôte que vous surveillez :
sudo -u <site> ls -la ~/var/check_mk/discovered_host_labels - Sur les sites Pro, Ultimate, Cloud et Ultimate MT, cherchez des journaux HTML hors du dossier attendu :
sudo -u <site> find ~/var/robotmk/html_logs -type f 2>/dev/nullUn fichier sous un chemin qui contient..ne peut pas exister comme nom littéral, donc examinez les fichiers dont les dossiers parents ne sont pas des dossiers de cas de test que vous reconnaissez.
Un résultat est une piste à examiner, pas une preuve d'exploitation. Le journal d'audit n'aide que si le changement de règle de l'attaquant a été enregistré et que le journal n'a pas été modifié ensuite.
Chronologie
- 2026-10-29 : le correctif de CVE-2026-118965 est commité dans le dépôt Checkmk.
- 2026-11-02 : le correctif de CVE-2026-120495 est consigné dans son werk.
- 2026-11-03 : le correctif de CVE-2026-121374 est commité dans le dépôt Checkmk.
- 2026-11-11 : Checkmk publie 2.5.0p19 et 2.4.0p40 et publie les trois enregistrements CVE.
FAQ
Cette faille concerne-t-elle l'édition Community ?
Oui pour CVE-2026-121374 et CVE-2026-118965, qui touchent toutes les éditions. CVE-2026-120495 ne touche que les éditions Pro, Ultimate, Cloud et Ultimate MT, car la supervision synthétique Robotmk ne fait pas partie de l'édition Community. Les paquets corrigés 2.5.0p19 et 2.4.0p40 existent pour toutes les éditions.
Je ne surveille pas Kubernetes. Suis-je quand même concerné par la première faille ?
Oui, si un utilisateur peut modifier des règles. L'attaquant crée la règle d'agent spécial Kubernetes, donc le site n'a pas besoin de surveiller un cluster. Retirez la permission de modification des règles des rôles non administratifs jusqu'à la mise à jour.
La version 2.3.0 est-elle corrigée ?
Non. La branche 2.3.0 est en fin de vie, et les trois werks la listent comme concernée sans version corrigée. Migrez ces sites vers 2.4.0p40 ou 2.5.0p19.
L'une de ces failles a-t-elle été exploitée dans la nature ?
Aucune exploitation n'est connue au 11 novembre 2026, et aucune des trois CVE ne figure dans le catalogue KEV de la CISA. La faille Kubernetes a été trouvée lors d'une revue interne, et la faille des étiquettes d'hôtes est arrivée par le processus de divulgation de sécurité de l'éditeur. La situation peut changer, donc consultez le catalogue KEV avant de planifier un délai long.
Dois-je modifier ma configuration après la mise à jour ?
Non. Les trois werks sont marqués compatibles sans interaction manuelle. L'agent Kubernetes accepte la nouvelle option par rôle, et les contrôles des étiquettes d'hôtes et de Robotmk appliquent automatiquement les nouvelles règles de chemin.
Comment savoir quelle édition j'utilise ?
omd version affiche la version de chaque site, et le nom du paquet sur le serveur indique l'édition, par exemple check-mk-raw pour Community ou check-mk-enterprise pour Enterprise. L'interface web affiche l'édition sous Help > About.
Trouver les serveurs Checkmk exposés avec Ostorlab
Utilisez Ostorlab Attack Surface Discovery pour inventorier les hôtes et interfaces web exposés à Internet que vous possédez, afin de savoir quels sites Checkmk sont joignables et doivent être mis à jour en premier. Il cartographie les services exposés ; il ne détecte pas cette CVE.
Références
- Werk Checkmk 17994, « Kubernetes: Arbitrary file write and code execution via excluded node roles », CVE-2026-121374, daté du 2026-11-03 : https://checkmk.com/werk/17994 (vérifié le 11 novembre 2026)
- Werk Checkmk 22120, « Code execution through compromised remote site », CVE-2026-118965, daté du 2026-10-29 : https://checkmk.com/werk/22120 (vérifié le 11 novembre 2026)
- Werk Checkmk 22624, « Code execution through Robotmk HTML log test service », CVE-2026-120495, daté du 2026-11-02 : https://checkmk.com/werk/22624 (vérifié le 11 novembre 2026)
- L'enregistrement CVE-2026-121374, CNA Checkmk, publié le 2026-11-11 : https://www.cve.org/CVERecord?id=CVE-2026-121374 (vérifié le 11 novembre 2026)
- L'enregistrement CVE-2026-118965, CNA Checkmk, publié le 2026-11-11 : https://www.cve.org/CVERecord?id=CVE-2026-118965 (vérifié le 11 novembre 2026)
- L'enregistrement CVE-2026-120495, CNA Checkmk, publié le 2026-11-11 : https://www.cve.org/CVERecord?id=CVE-2026-120495 (vérifié le 11 novembre 2026)
- Commit de correctif 5a2c448efa pour CVE-2026-121374, 2026-11-03 : https://github.com/Checkmk/checkmk/commit/5a2c448efafb1e3f2dab75babdecb5f99d0a0618 (vérifié le 11 novembre 2026)
- Commit de correctif 8efcf83a15 pour CVE-2026-118965, 2026-10-29 : https://github.com/Checkmk/checkmk/commit/8efcf83a153b201ce640a6c1da9de9c52d9c3650 (vérifié le 11 novembre 2026)
- Commit de correctif 4ba4c9f638 pour CVE-2026-120495, 2026-11-03 : https://github.com/Checkmk/checkmk/commit/4ba4c9f638cf83509970e78468f79bf846327d7b (vérifié le 11 novembre 2026)
- Index des notes de version Checkmk 2.5.0p19, daté du 11 novembre 2026 : https://checkmk.com/werks?version=2.5.0p19 (vérifié le 11 novembre 2026)
- Index des notes de version Checkmk 2.4.0p40, daté du 11 novembre 2026 : https://checkmk.com/werks?version=2.4.0p40 (vérifié le 11 novembre 2026)
- Le catalogue Known Exploited Vulnerabilities de la CISA, version 2026.11.10, qui ne liste pas les trois CVE : https://www.cisa.gov/known-exploited-vulnerabilities-catalog (vérifié le 11 novembre 2026)
- Figure 1, la chronologie correctif-version : dates issues des trois werks et des deux index de version cités dans les Références, vérifiés le 11 novembre 2026.