Marimo GHSL-2026-226 : TOCTOU dans le workflow de version de test
Une course d’horodatage dans la même seconde permettait à une mise à jour de pull request de franchir l’approbation de test d’un responsable et d’atteindre les jobs de publication TestPyPI et npm. Le workflow vulnérable a été supprimé ; aucun CVE n’a été attribué.
Un responsable de laboratoire approuve un échantillon précis, mais le laboratoire ne vérifie que la seconde affichée par l’horloge. Si quelqu’un remplace l’échantillon pendant cette même seconde, le nouveau semble approuvé. Le workflow Marimo a commis cette erreur avec un commit de pull request, puis a transmis le paquet compilé aux jobs de publication.
Concepts Clés et Termes
TOCTOU- Time-of-check to time-of-use : une ressource change après le contrôle de sécurité et avant son utilisation.
Publication OIDC- Un job CI échange une identité GitHub Actions contre des identifiants temporaires du registre de paquets, sans stocker de mot de passe à long terme.
Artefact de workflow- Ensemble de fichiers transféré entre jobs GitHub Actions. Un job en aval doit traiter les artefacts de workflows non fiables comme des entrées non fiables.
GHSL-2026-226- Identifiant de l’avis GitHub Security Lab pour cette faille du workflow Marimo. Aucun CVE n’a été attribué dans l’avis.
CWE-367 / CWE-829- L’avis identifie une course entre vérification et utilisation et l’exécution de fonctionnalité provenant d’un domaine de contrôle non fiable.
Correspondances de référentiels
Déroulement de l'Attaque Étape par Étape
Un responsable autorise une version de test
Un responsable commente une pull request pour lancer le workflow de version de test Marimo. L’autorisation devait concerner l’état de la pull request examiné.
La tête de la pull request change pendant la même seconde
Le workflow compare pushed_at du dépôt à created_at du commentaire après conversion en secondes entières. Un push pendant la même seconde donne une valeur égale.
Le contrôle vulnérable accepte l’égalité
Le workflow supprimé rejetait uniquement les valeurs pushed_at strictement postérieures à l’heure du commentaire. L’égalité passait et le commit actualisé était enregistré.
Du code non fiable construit les artefacts de paquet
Le job récupérait ce commit et exécutait des actions et scripts de build contrôlés par le dépôt. Les résultats étaient téléversés comme artefacts puis consommés par les jobs de publication sans reconstruction depuis un commit de confiance.
Le pouvoir de publication atteint la sortie non fiable
Les jobs TestPyPI et npm utilisaient des permissions de publication OIDC. L’avis décrit la possibilité pour l’artefact d’atteindre la publication ; il ne signale pas la compromission réelle d’un paquet.
Code Source : Vulnérable vs Sécurisé
GHSL-2026-226 indique que le workflow vulnérable a été supprimé dans la PR #10765 ; cela ne signifie pas que le projet a appliqué le changement de comparateur illustré. L’ancien contrôle utilisait -gt, donc des horodatages égaux à la seconde passaient. Le contrôle illustratif -ge rejette l’égalité, mais il vaut mieux lier l’autorisation au commit exact révisé. Séparez les builds non fiables des jobs OIDC, reconstruisez depuis le SHA autorisé et vérifiez la provenance avant publication. Aucun payload d’exploitation n’est inclus.
# Workflow marimo-bot supprimé : comparaison en secondes entières
if [[ $(date -d "$pushed_at" +%s) -gt $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# Le head_sha obtenu était récupéré et ses artefacts
# transmis à des jobs de publication distincts.
# Contrôle illustratif ; GHSL indique que le workflow vulnérable
# a été supprimé, et non corrigé sur place.
if [[ $(date -d "$pushed_at" +%s) -ge $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
# Conception plus robuste : autoriser un SHA immuable révisé,
# reconstruire depuis ce SHA dans un job fiable, puis publier des sorties vérifiées.
Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Supprimez ou remplacez les copies concernées du workflow marimo bot supprimé et confirmez que le dépôt actuel n’active plus le chemin de publication vulnérable.
- ✓Liez l’approbation du responsable au SHA immuable exact de la pull request et échouez si celui-ci change avant le checkout.
- ✓N’utilisez pas des horodatages à la seconde comme seule preuve qu’une branche mobile correspond à la version approuvée.
- ✓Construisez les pull requests non fiables sans identifiants de publication ; réservez id-token: write à un job de publication fiable distinct.
- ✓Reconstruisez les paquets depuis le commit autorisé dans le flux fiable au lieu de promouvoir des artefacts créés par du code non fiable.
- ✓Vérifiez la provenance, la révision source, le contenu du paquet et la cible avant toute publication sur TestPyPI ou npm.
- ✓Traitez l’avis GHSL comme preuve d’un chemin vulnérable, pas d’une compromission ou exploitation réelle d’un paquet.
Sources
- Avis GitHub Security Lab GHSL-2026-226 — reported by Jaroslav Lobačevski
- Pull request Marimo #10765 supprimant le workflow vulnérable
- GitHub Security Lab : prévenir les pwn requests
- MITRE CWE-367 : condition de concurrence TOCTOU
- MITRE CWE-829 : inclusion de fonctionnalité issue d’un domaine de contrôle non fiable
- Cas de workflow lié (distinct) : JupyterLab CVE-2026-84973