
Compétence d'agent qui audite une base de code Rails pour la CVE-2026-66066 (KindaRails2Shell) — lecture arbitraire de fichiers / RCE via Active Storage + libvips, en vérifiant les versions de Rails et libvips ainsi que les mitigations block-untrusted.
Une Agent Skill qui audite les dépôts Ruby on Rails pour détecter l'exposition à CVE-2026-66066 (KindaRails2Shell) — la vulnérabilité de traitement des variantes libvips d'Active Storage qui permet la lecture arbitraire de fichiers et, dans une application Rails, l'exécution de code à distance.
La skill est un outil d'audit de configuration et d'aide à la remédiation. Elle ne contient aucun code d'exploit et ne décrit pas la chaîne d'attaque.
| CVE | CVE-2026-66066 |
| Gravité | Critique, CVSS 9.5 |
| Paquet | activestorage (RubyGems) |
| Affecté | < 7.2.3.2, >= 8.0 < 8.0.5.1, >= 8.1 < 8.1.3.1 |
| Corrigé | 7.2.3.2, 8.0.5.1, 8.1.3.1 |
| Avis | GHSA-xr9x-r78c-5hrm |
libvips lit et écrit des formats via des opérations, dont certaines sont marquées comme unfuzzed — non sûres pour du contenu non fiable. Active Storage ne les désactivait pas, de sorte qu'un attaquant capable de téléverser un fichier forgé peut les atteindre.
Une application est exposée uniquement lorsque les quatre conditions suivantes sont réunies :
activestorage se trouve dans une plage de versions affectéeconfig.active_storage.variant_processor est résolu à :vipsLa condition 3 est la condition discriminante. La plage affectée < 7.2.3.2 inclut toutes les versions de Rails 6.x, mais 6.x utilise :mini_magick par défaut, donc 6.x n'est exposé que sous une configuration non par défaut, et les versions antérieures à 6.0 n'ont aucun paramètre variant_processor. Rails 7.0 et ultérieur utilisent :vips par défaut via config.load_defaults 7.0, ce qui explique pourquoi la configuration courante est exposée. Rails 8.1 accepte également :disabled, ce qui rend la condition 3 fausse.
En tant que plugin Claude Code, via le marketplace fourni dans ce dépôt :
/plugin marketplace add paveg/rails-activestorage-vips-audit
/plugin install rails-activestorage-vips-audit@paveg-skills
Avec le CLI skills, qui installe la même compétence dans Claude Code, Codex, Cursor, Copilot CLI et d'autres agents :
npx skills add paveg/rails-activestorage-vips-audit
Ou manuellement :
git clone https://github.com/paveg/rails-activestorage-vips-audit.git
cp -r rails-activestorage-vips-audit/skills/rails-activestorage-vips-audit ~/.claude/skills/
~/.agents/skills/ fonctionne comme un emplacement inter-runtime pour Codex, Copilot CLI et Gemini CLI. Rien dans la compétence ne dépend de l'endroit où elle est installée — il n'y a pas de chemins absolus, et collect-evidence.sh résout tout relativement à la racine de l'application vers laquelle il est pointé.
La compétence dispose de deux modes, et les deux acceptent plusieurs chemins d'application.
report <app>... # read-only audit, one verdict per application
fix <app>... # applies remediation on a branch; never commits or pushes unprompted
Installé en tant que plugin, chaque mode est également une commande, ce qui évite de devoir saisir le mode comme argument :
/rails-activestorage-vips-audit:report path/to/app another/app
/rails-activestorage-vips-audit:fix path/to/app
Les commandes sont des points d'entrée pour vous, pas pour l'agent : elles sont marquées de sorte que Claude ne les déclenche jamais de lui-même. Claude invoque néanmoins la skill elle-même lorsqu'une requête y correspond, c'est pourquoi fix ne peut pas démarrer sans qu'un humain le demande.
report est la commande par défaut. fix nécessite d'abord un verdict report pour la même application, car la remédiation correcte en dépend — Rails 6.x, 7.0.x et 7.1.x n'ont pas de correctif dans la même série, donc fix y applique l'atténuation provisoire et signale qu'une mise à niveau du framework est requise plutôt que de tenter d'en effectuer une.
La collecte de preuves peut également être exécutée de manière autonome :
skills/rails-activestorage-vips-audit/scripts/collect-evidence.sh path/to/app another/app
Le script collecte des faits et ne contient délibérément aucune logique de verdict. Indiquez une racine d'application, pas une racine de monorepo indifférenciée. Pour un monorepo, indiquez chaque répertoire Rails déployable possédant son propre Gemfile.lock et config/application.rb comme argument distinct. Le collecteur exclut ces racines d'application imbriquées du flux de preuves du parent, tout en conservant les racines de lockfile imbriquées qui peuvent être des moteurs montés ou des dépendances de chemin.
vips --version là où l'application s'exécute. Les rapports classent ce point sous la préparation à l'exécution et la remédiation plutôt que de rendre le verdict d'exposition conditionnel.VIPS_BLOCK_UNTRUSTED dans un Dockerfile ne prouve pas que l'environnement déployé le définit. La compétence plafonne ces constats à « atténuation provisoire présente, mise à niveau toujours requise » et ne laisse jamais l'un d'eux produire un verdict propre.Mettez à niveau vers 7.2.3.2, 8.0.5.1 ou 8.1.3.1, selon votre série. Confirmez d'abord libvips à l'exécution >= 8.13 et ruby-vips >= 2.2.1 : là où ruby-vips est installé, l'Active Storage corrigé lève une exception au démarrage à moins que les deux conditions ne soient remplies, et cette vérification s'applique aussi aux applications :mini_magick.
Atténuations provisoires, dont aucune ne remplace la mise à niveau :
VIPS_BLOCK_UNTRUSTED (libvips >= 8.13 ; aucune modification de gem nécessaire)Vips.block_untrusted(true) depuis un initializer (ruby-vips >= 2.2.1, plus libvips >= 8.13)Sur ruby-vips < 2.2.1, la voie de l'initializer appelle une méthode qui n'existe pas encore ; élevez donc d'abord la gem ou empruntez la voie de la variable d'environnement, qui n'en dépend pas.
Si une application a été exposée, considérez chaque secret lisible par le processus de l'application comme compromis et faites-les tourner : secret_key_base, la clé maître, les identifiants de service Active Storage, les identifiants de base de données et les jetons tiers.
Un WAF n'est pas une atténuation ici. Qu'il puisse voir la charge utile dépend du service de stockage et de la méthode d'envoi, son efficacité est donc trop dépendante de la configuration pour être fiable.