Clé en laiton antique posée sur une surface d'obsidienne noire avec une ombre marquée.

Vulnérabilité GitHub : champs privés exposés via CEL et NativeTypes

Un champ marqué json:"-" peut être lu par n’importe quel utilisateur via une expression CEL, contournant ainsi la directive d’omission prévue par l’encodage JSON. C’est le cœur de la vulnérabilité GHSA-gcjh-h69q-9w9g, qui impacte la manière dont GitHub gère les structures de données natives.

Le problème réside dans la fonction fieldNameByTag utilisée par ParseStructTag("json"). Lorsque ce mécanisme lit les balises de structure Go, il interprète la balise json:"-" non pas comme un signal pour ignorer le champ, mais comme un nom de champ littéral, soit "-". Cela contredit directement le comportement standard de l’encodage JSON, où un champ tagué de cette manière devrait être systématiquement omis.

Cette mauvaise interprétation n’est pas seulement cosmétique ; elle permet d’accéder au champ. Une fois ce champ nommé "-" enregistré dans le système de types CEL, il devient accessible au runtime. Un utilisateur malveillant peut alors lire la valeur correspondante en utilisant une syntaxe d’accès par crochet, comme dyn(req.auth)["-"].

Collage en papier découpé représentant une pile de manuels techniques d'où s'échappe un signe de guillemet.

En plus de ce défaut spécifique, l’annonce de github.com souligne un problème secondaire mais potentiellement dangereux : newNativeTypes enregistre silencieusement toutes les structures imbriquées atteignables à partir du type initial, y compris celles issues de dépendances tierces que le développeur n’a jamais examinées.

Les conséquences techniques de cette mauvaise lecture

Ce mécanisme défaillant se propage à travers l’écosystème de type de GitHub. La fonction FindStructFieldNames liste ce champ, le traitant comme une entité valide. Pire encore, la fonction FindStructFieldType permet ensuite de récupérer la valeur sous-jacente du champ, car le nom "-" est accepté comme un identifiant légitime dans le système.

L’impact est d’autant plus grave que le processus de conversion des objets natifs en valeurs au format JSON-like CEL ne filtre pas cette anomalie, insérant le champ "-" dans la sortie sans appliquer la règle d’omission JSON. Les développeurs s’attendent, en utilisant ParseStructTag("json"), à une sémantique d’encodage standard, ce qui n’est pas le cas ici.

Des préoccupations similaires dans d’autres couches logicielles

Ce genre de décalage entre la documentation attendue et le comportement réel n’est pas une nouveauté dans le domaine des systèmes complexes. Par exemple, dans l’écosystème des API, des changements majeurs dans les dépendances peuvent entraîner des ruptures inattendues. Apigee, par exemple, passe à Java 21 LTS, ce qui entraîne la suppression de modules Java EE et CORBA hérités. Les politiques JavaCallout personnalisées peuvent se casser en raison de l’accès non autorisé à des paquets internes comme sun.security.* ou en raison de la modification des signatures de méthodes.

Ces changements obligent les équipes à vérifier minutieusement leur code pour éviter les NoClassDefFoundError ou les InaccessibleObjectException lors des mises à jour, une tâche qui demande une vigilance constante des développeurs.

Il faut surveiller comment GitHub gère l’implémentation de ses outils de sécurité internes ; le fait que des mécanismes de validation de noms soient contournés par une simple interprétation d’une balise de métadonnées pose une question sur la robustesse globale de l’infrastructure.

Sources