Rexact
Cheatsheet

Regex référence d'image Docker (nom:tag@digest)

Une référence d'image s'écrit [registre[:port]/]chemin[:tag][@digest]. Les composants du chemin sont en minuscules et chiffres, séparés par un point, un ou deux tirets bas ou plusieurs tirets ; le registre est un nom DNS (ou une adresse IPv6 entre crochets) avec port facultatif ; le tag fait 1 à 128 caractères parmi lettres, chiffres, tiret bas, point, tiret, sans commencer par un point ni un tiret ; le digest est algorithme:hexadécimal d'au moins 32 chiffres. Ces règles sont celles du paquet reference de Docker/distribution. Les trois tentatives réelles relues s'en écartent : le parseur d'Aspire accepte les majuscules, « <tag> » et tout digest, celui de docker-parse-image accepte presque toute chaîne, et le port JavaScript d'un ancien motif de Docker n'a pas terminé en plus de 100 secondes sur 40 « a » suivis d'un « ! ». Voici le motif officiel, converti en JavaScript.

/^(?:(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))*|\[[a-fA-F0-9:]+\])(?::[0-9]+)?/)?[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*(?::[\w][\w.-]{0,127})?(?:@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,})?$/
passe 27/27 cas

Comparatif des patterns existants

SourcepatternScore sur le corpusReDoS
Aspire (.NET, ContainerReferenceParser) — accepte les majuscules (« Ubuntu »), un tag commençant par un tiret, « <tag> », un tag de plus de 128 caractères, « a___b » et n'importe quel digest ; groupes nommés convertis tels quels^((?<registry>((localhost|\[(?:[a-fA-F0-9:]+)\]|([\w-]+(\.[\w-]+)+))(:\d+)?)|([\w-]+:\d+))\/)?(?<image>[\w-./<>]+)(:(?<tag>[\w-.<>]+))?(@(?<digest>.+))?$16 / 27sûr
docker-parse-image (npm) — conçu pour découper, pas valider : accepte espaces, majuscules, « http://registry/app » et « ubuntu:latest:extra »^(?:([^\/]+)\/)?(?:([^\/]+)\/)?([^@:\/]+)(?:[@:](.+))?$14 / 27sûr
@jkcfg/kubernetes (npm, image-reference.js) — port JavaScript d'un ancien motif de Docker : séparateur « [-]* » imbriqué sous des quantificateurs, backtracking catastrophique (40 « a » suivis de « ! » : plus de 100 s sans réponse) ; pas d'IPv6^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?\/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?(?:(?:\/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?)(?::([\w][\w.-]{0,127}))?(?:@([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][0-9a-fA-F]{32,}))?$26 / 27vulnérable (g/ag0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g0g…)

Implémentation

const re = new RegExp("^(?:(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))*|\\[[a-fA-F0-9:]+\\])(?::[0-9]+)?/)?[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*(?:/[a-z0-9]+(?:(?:[._]|__|[-]+)[a-z0-9]+)*)*(?::[\\w][\\w.-]{0,127})?(?:@[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*:[0-9a-fA-F]{32,})?$", "");
re.test(input);

Limites

  • Valide seulement la FORME : ne prouve pas que l'image ou le registre existent, ni que le digest correspond à un contenu. Le digest n'est pas vérifié : seul « algorithme:32 hexadécimaux ou plus » est contrôlé (sha256 attend 64 chiffres).
  • Le code officiel de Docker limite aussi le nom (registre compris) à 255 caractères, hors de la regex : ce motif ne vérifie pas cette longueur. Il accepte « ubuntu » seul, sans registre ni tag, et ne normalise pas (docker.io/library/, tag latest).
  • Un nom de la forme « a.b/c » est lu comme registre « a.b » : la règle « domaine si un point ou un port » appartient au code, pas au motif. Les registres internationalisés (IDN) et les zones IPv6 sont rejetés, comme dans le motif officiel.

Pages liées