DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Uncategorized»Le document YAML de l’enfer — Édition JavaScript
    Uncategorized

    Le document YAML de l’enfer — Édition JavaScript

    mars 1, 2023
    Le document YAML de l'enfer — Édition JavaScript
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Je suis récemment tombé sur ce billet de blog de Ruud van Asseldonk intitulé « Le document YAML de l’enfer ». J’ai toujours entendu dire que YAML avait ses pièges, mais je n’avais pas examiné les détails et, heureusement, je n’avais pas été affecté, principalement en raison de mon utilisation très peu fréquente et simple de YAML. Si vous êtes dans le même bateau que moi, je vous recommande de lire cet article maintenant, car je n’arrive presque pas à croire que j’ai évité tout problème avec.

    L’article explore les problèmes de la spécification YAML elle-même, puis décrit ce qui se passe dans PyYAML de Python et la bibliothèque YAML de Golang avec un exemple de fichier, le document YAML titulaire de l’enfer. Je voulais voir comment les choses se passaient dans l’écosystème JavaScript.

    YAML en JavaScript

    Une recherche d’analyseurs JavaScript YAML sur npm fait apparaître YAML (que j’ai utilisé dans mon propre projet) et js-yaml. js-yaml a le plus de téléchargements hebdomadaires selon npm et le plus d’étoiles sur GitHub cependant, YAML semble être en développement plus actif, ayant été publié le plus récemment (il y a un mois au moment de la rédaction) par rapport à la dernière publication de js-yaml date d’il y a presque 2 ans. Il y a aussi yamljs, mais le projet n’a pas reçu d’engagement depuis novembre 2019 et n’est pas sorti depuis 6 ans, donc je vais l’ignorer pour l’instant.

    Voyons ce que YAML et js-yaml font avec le document YAML de l’enfer.

    Le document lui-même

    Pour vous éviter des allers-retours entre l’article de van Asseldonk et celui-ci, voici le document YAML.

    server_config:
      port_mapping:
        # Expose only ssh and http to the public internet.
        - 22:22
        - 80:80
        - 443:443
    
      serve:
        - /robots.txt
        - /favicon.ico
        - *.html
        - *.png
        - !.git  # Do not expose our Git repository to the entire world.
    
      geoblock_regions:
        # The legal team has not approved distribution in the Nordics yet.
        - dk
        - fi
        - is
        - no
        - se
    
      flush_cache:
        on: [push, memory_pressure]
        priority: background
    
      allow_postgres_versions:
        - 9.5.25
        - 9.6.24
        - 10.23
        - 12.13

    Alors, comment nos bibliothèques JavaScript gèrent-elles ce fichier ?

    Les échecs

    Ancres, alias et balises

    Commençons par les échecs. Comme décrit dans l’article d’origine sous le sous-titre « Ancres, alias et balises », cette section n’est pas valide :

      serve:
        - /robots.txt
        - /favicon.ico
        - *.html
        - *.png
        - !.git  # Do not expose our Git repository to the entire world.

    Cela provoque l’émission d’une erreur par nos deux bibliothèques JavaScript YAML, toutes deux faisant référence à un alias non défini. C’est parce que le * est un moyen de référencer une ancre créée précédemment dans le document à l’aide d’un &. Dans le cas de notre document, cette ancre n’a jamais été créée, il s’agit donc d’une erreur d’analyse.

    Si vous voulez en savoir plus sur les ancres et les alias, cela semble être quelque chose d’important dans les pipelines de construction. Bitbucket et GitLab ont écrit sur la façon d’utiliser les ancres pour éviter de répéter des sections dans les fichiers yaml.

    Dans le but d’essayer d’analyser le fichier, nous pouvons créer ces chaînes d’alias comme elles étaient probablement destinées.

    serve:
        - /robots.txt
        - /favicon.ico
        - "*.html"
        - "*.png"
        - !.git  # Do not expose our Git repository to the entire world.

    Maintenant, nous obtenons une autre erreur d’analyse de nos bibliothèques ; les deux se plaignent d’une balise inconnue ou non résolue. Le ! au début de !.git est le personnage qui déclenche ce comportement.

    Les balises semblent être la partie la plus compliquée de YAML pour moi. Ils dépendent de l’analyseur que vous utilisez et permettent à cet analyseur de faire quelque chose de personnalisé avec le contenu qui suit la balise. Si j’ai bien compris, vous pouvez l’utiliser en JavaScript pour, par exemple, baliser du contenu à analyser dans un Map au lieu d’un Object ou un Set au lieu d’un Array. Van Asseldonk explique cela avec cette phrase alarmante :

    Cela signifie que le chargement d’un document YAML non approuvé n’est généralement pas sûrcar cela peut conduire à l’exécution de code arbitraire.

    PyYaml a apparemment un safe_load méthode qui évitera cela, mais pas le package yaml de Go. Il semble que les bibliothèques JavaScript manquent également de cette fonctionnalité, donc l’avertissement pour les documents YAML non fiables est maintenu.

    Si vous souhaitez tirer parti de la fonctionnalité de balise dans yaml, vous pouvez consulter la documentation du package yaml sur les types de données personnalisés ou les types yaml pris en charge par js-yaml et les extensions de type non sécurisées.

    Pour analyser le fichier YAML, enfermons tous les artefacts yaml étranges entre guillemets pour en faire des chaînes :

    serve:
        - /robots.txt
        - /favicon.ico
        - "*.html"
        - "*.png"
        - "!.git"  # Do not expose our Git repository to the entire world.

    Avec le serve bloc regardant ci-dessus, le fichier analyse maintenant. Alors, qu’arrive-t-il au reste des pièges potentiels de yaml ?

    Numéros accidentels

    Une chose que je retiens de cette enquête jusqu’à présent est que si vous avez besoin que quelque chose soit une chaîne, ne soyez pas ambigu à ce sujet, entourez-le de guillemets. Cela comptait pour les alias et les balises ci-dessus et cela compte également pour les nombres accidentels. Dans la section suivante du fichier yaml, vous voyez une liste de numéros de version :

     allow_postgres_versions:
        - 9.5.25
        - 9.6.24
        - 10.23
        - 12.13

    Les numéros de version sont des chaînes, les nombres ne peuvent pas contenir plus d’un point décimal. Mais lorsque ceci est analysé par l’une ou l’autre des bibliothèques JavaScript, le résultat est le suivant :

    allow_postgres_versions: [ '9.5.25', '9.6.24', 10.23, 12.13 ]

    Nous avons maintenant un tableau de chaînes et de nombres. Si un analyseur YAML pense que quelque chose ressemble à un nombre, il l’analysera comme tel. Et lorsque vous en venez à utiliser ces valeurs, elles peuvent ne pas agir comme prévu.

    Numéros de version dans les actions GitHub

    J’ai déjà eu ce problème dans GitHub Actions. C’était dans un projet Ruby, mais cela s’applique à toute personne essayant d’utiliser des numéros de version dans un fichier YAML GitHub Actions. J’ai essayé d’utiliser une liste de numéros de version de Ruby, cela a bien fonctionné jusqu’à la sortie de la version 3.1 de Ruby. J’avais 3.0 dans le tableau. Dans GitHub Actions, cela a été analysé comme un entier 3. Cela peut sembler correct, sauf que lorsque vous donnez une version entière à GitHub Actions, il sélectionne le dernier point mineur pour cette version. Ainsi, une fois Ruby 3.1 sorti, le nombre 3.0 sélectionnerait la version 3.1. J’ai dû faire du numéro de version une chaîne, "3.0"puis il a été appliqué correctement.

    Les nombres accidentels causent des problèmes. Si vous avez besoin d’une chaîne, assurez-vous de fournir une chaîne.

    Les Succès

    Tout n’est pas si mal dans le monde JavaScript. Après avoir résolu les problèmes ci-dessus, nous pourrions maintenant être clairs. Voyons maintenant ce qui a été correctement analysé à partir de ce fichier YAML.

    Nombres sexagésimaux

    Sous la section de mappage de port du fichier YAML, nous voyons :

      port_mapping:
        # Expose only ssh and http to the public internet.
        - 22:22
        - 80:80
        - 443:443

    Ce 22:22 est dangereux dans la version 1.1 de yaml et PyYaml l’analyse comme un nombre sexagésimal (base 60), donnant le résultat de 1342. Heureusement, les deux bibliothèques JavaScript ont implémenté YAML 1.2 et 22:22 est analysé correctement comme une chaîne dans ce cas.

      port_mapping: [ '22:22', '80:80', '443:443' ]

    Le problème norvégien

    Dans YAML 1.1 no est analysé comme false. C’est ce qu’on appelle le « problème de la Norvège », car il est assez courant de répertorier les pays sous la forme d’identifiants à deux caractères et d’avoir ce YAML :

      geoblock_regions:
        - dk
        - fi
        - is
        - no
        - se

    Parsé dans ce JavaScript :

      geoblock_regions: [ 'dk', 'fi', 'is', false, 'se' ]

    Ce n’est tout simplement pas utile. La bonne nouvelle est que, contrairement à la bibliothèque YAML de Go, les deux bibliothèques JavaScript ont implémenté YAML 1.2 et abandonné no comme alternative pour false. Le geoblock_regions sections est analysé avec succès comme suit :

      geoblock_regions: [ 'dk', 'fi', 'is', 'no', 'se' ]

    Clés sans chaîne

    Vous pourriez croire que les clés dans YAML seraient analysées comme des chaînes, comme JSON. Cependant, ils peuvent prendre n’importe quelle valeur. Encore une fois, il y a des valeurs qui peuvent vous faire trébucher. Tout comme avec le problème de la Norvège dans lequel yes et no peut être analysé comme true et falseC’est la même chose pour on et off. Cela se manifeste dans notre fichier YAML dans le flush_cache section:

     flush_cache:
        on: [push, memory_pressure]
        priority: background

    Ici la clé est on, mais dans certaines bibliothèques, il est analysé comme un booléen. En Python, encore plus déroutant, le booléen est ensuite transformé en chaîne et apparaît comme la clé "True". Heureusement, cela est géré par les bibliothèques JavaScript et on devient la clé "on".

      flush_cache: { on: [ 'push', 'memory_pressure' ], priority: 'background' }

    Ceci est à nouveau particulièrement préoccupant dans GitHub Actions, où on est utilisé pour déterminer quels événements doivent déclencher une action. Je me demande si GitHub a dû contourner ce problème lors de la mise en œuvre de leur analyse.

    Analyse en tant que YAML version 1.1

    La plupart des problèmes que nos bibliothèques JavaScript évitent sont des problèmes de YAML 1.1 et les deux bibliothèques ont entièrement implémenté YAML 1.2. Si vous souhaitez faire preuve de prudence ou si vous devez analyser explicitement un fichier yaml avec les paramètres YAML 1.1, la bibliothèque YAML peut le faire pour vous. Vous pouvez passer un deuxième argument au parse fonction pour lui dire d’utiliser la version 1.1, comme ceci :

    import { parse } from "yaml";
    const yaml = parse(yamlContents, { version: "1.1" });
    console.log(yaml);

    Vous obtenez maintenant un résultat avec tout le plaisir décrit ci-dessus :

    {
      server_config: {
        port_mapping: [ 1342, '80:80', '443:443' ],
        serve: [ '/robots.txt', '/favicon.ico', '*.html', '*.png', '!.git' ],
        geoblock_regions: [ 'dk', 'fi', 'is', false, 'se' ],
        flush_cache: { true: [ 'push', 'memory_pressure' ],...
    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.