
Boîte à outils d'investigation numérique et compétences d'agent pour enquêter sur Rails Active Storage/libvips CVE-2026-66066 : détecte les indicateurs de blobs malveillants, les fenêtres d'exposition et l'exfiltration de données.
Outillage et méthode pour répondre à deux questions concernant une application Rails et CVE-2026-66066, la lecture arbitraire de fichiers via Active Storage et libvips connue sous le nom de KindaRails2Shell :
L'avis GHSA-xr9x-r78c-5hrm expliquait la vulnérabilité et nommait les versions corrigées, mais ne divulguait pas suffisamment de détails pour évaluer ces questions. Ce projet vise à y remédier.
Il s'agit d'un dépôt de documentation et de compétences plutôt que d'une bibliothèque. Rien ici ne s'installe dans votre application. Un agent le lit et travaille sur votre application récupérée ailleurs, et le seul script qui s'exécute en production est un fichier autonome unique que vous copiez dans un conteneur.
Rails décide qu'un blob peut être traité comme image en lisant une colonne content_type
qu'un téléversement direct permet au client de définir sans que les octets soient jamais examinés.
libvips décide ensuite de ce qu'est réellement le fichier en reniflant les octets magiques. Un fichier
dont les dix premiers octets revendiquent MATLAB 5.0 est routé vers le chargeur MATLAB de libvips,
qui le transmet à libmatio, qui se base sur une autre plage d'octets et
trouve MAT 7.3, qui est HDF5. La External File List de HDF5 permet aux octets d'un jeu de données
de résider dans un autre fichier nommé par chemin et décalage, de sorte que le rendu de l'« image » lit un
fichier choisi par l'attaquant sur le serveur et renvoie son contenu sous forme de pixels. La même
confusion, deux fois, à deux couches qui ne peuvent pas voir les champs l'une de l'autre.
reference/the-attack.md retrace toute la chaîne d'appels, de la requête entrante
jusqu'au point où libmatio ouvre le fichier cible, avec les quatre jonctions
essentielles marquées. reference/the-investigation.md explique ensuite pourquoi l'attaque
est investigable du tout : elle laisse trois artefacts de force croissante, et
le plus fort d'entre eux est la variante rendue, qui conserve les octets volés sous forme de
valeurs de pixels dans votre propre stockage d'objets.
Les deux compétences s'exécutent dans l'ordre. La première produit la fenêtre d'exposition ; la seconde ne peut pas démarrer sans elle.
| Compétence | Question | Produit |
|---|---|---|
kr2s-was-i-vulnerable | Cette application a-t-elle déjà été exposée ? | Une fenêtre d'exposition et les faits dont le balayage a besoin |
kr2s-was-i-exploited | Quelqu'un l'a-t-il utilisée, et qu'a-t-il obtenu ? | Une analyse forensique écrite |
Les deux sont écrites pour un agent, et les deux sont lisibles par une personne qui souhaite faire
le travail à la main. Chacune possède un point d'entrée SKILL.md et un references/guide.md
contenant le processus réel, ses contrôles d'évaluation et ses modes de défaillance.
Si vous êtes corrigé et voulez savoir si vous devez vous en soucier, exécutez la première. Son livrable est une fenêtre plutôt qu'un oui ou non, car pour la plupart des gens qui lisent ceci, la réponse au présent est « non, nous avons corrigé », et la réponse utile est quelles années une investigation devrait couvrir.
Clonez ce dépôt et conservez le clone. Les deux compétences partagent les documents de référence
dans reference/, et leurs guides les lisent par chemin relatif au dépôt, donc un répertoire de compétence copié
seul ailleurs aboutira à une impasse.
Le plus simple est de démarrer votre agent à l'intérieur du clone et de lui indiquer où se trouve votre
application. AGENTS.md l'oriente à partir de là, y compris la partie que les gens se trompent, à savoir que
ce dépôt est l'outil et non le sujet.
Sinon, pointez vers le fichier et dites-le, ce qui fonctionne dans tout agent capable de lire des fichiers locaux :
Read /path/to/rails-forensics-CVE-2026-66066/skills/kr2s-was-i-vulnerable/SKILL.md
and follow it. My application is at /path/to/my-app.
Dans Claude Code, vous pouvez plutôt les installer pour qu'ils se déclenchent d'eux-mêmes, en créant un lien symbolique plutôt qu'en les copiant, ce qui les maintient pointés vers le clone :
ln -s "$PWD/skills/kr2s-was-i-vulnerable" ~/.claude/skills/
ln -s "$PWD/skills/kr2s-was-i-exploited" ~/.claude/skills/
Utilisez .claude/skills/ à l'intérieur d'un projet plutôt que ~/.claude/skills/ si vous
préférez les limiter à une seule application.
Dans les deux cas, indiquez à l'agent où se trouve votre application. Les skills précisent explicitement que ce dépôt et l'application faisant l'objet de l'investigation sont deux racines distinctes, et qu'ils peuvent lire la seconde mais jamais y écrire.
AGENTS.md orientation for an agent started in this directory
reference/the-attack.md how the vulnerability works, traced call by call
reference/the-investigation.md why an investigation is possible, and where it runs out
skills/ the two skills
RUNBOOK.md operator's guide to the scanner: flags, verdicts, resuming
lib/crafted_mat_file.rb the detector
bin/ the scanner and three analysis utilities
test/ the test suite
Les deux documents de référence constituent la moitié en langage clair de ce dépôt et se suffisent à eux-mêmes. Lisez-les si vous voulez comprendre le problème, exécutez les skills si vous voulez une réponse concernant une application particulière.
bin/kr2s_scan_active_storage_blobs.rb est généré à partir de lib/ par rake build
et commité, donc l'exécuter en production ne nécessite aucune étape de build ni aucun second
fichier.
lib/crafted_mat_file.rb identifie le fichier fabriqué que cette attaque requiert. Il
lit deux champs d'en-tête dans les 128 premiers octets d'un objet et n'a besoin
de rien d'autre, ce qui explique pourquoi le scan peut classer un candidat à partir d'une lecture
ciblée plutôt que de le télécharger. reference/the-attack.md explique quels champs et
pourquoi aucun writer légitime ne produit cette combinaison.
Ce dépôt ne fournit délibérément aucun code qui construit des fichiers fabriqués, et aucun
fichier fabriqué. Les tests du détecteur synthétisent les 128 octets d'en-tête dont ils ont
besoin en pur Ruby, ce qui est tout ce que lit le détecteur. reference/the-attack.md
décrit complètement la structure, donc rien n'est dissimulé à un lecteur
cherchant à comprendre l'attaque. Ce qui est retenu, c'est un générateur fonctionnel qui
pourrait être redirigé vers un chemin arbitraire en changeant un seul argument.
Couvert : Active Storage, sur les applications utilisant le processeur de variantes
:vips, où les enregistrements de variantes étaient suivis.
Non couvert : tout autre endroit où une application confie des fichiers fournis par l'utilisateur à
libvips. Les autres bibliothèques d'upload, les clients directs de stockage d'objets et les systèmes
sur mesure d'avatars ou de logos nécessitent chacun leur propre balayage, et le scanner présent ici ne
le fera pas. kr2s-was-i-vulnerable vous fera les énumérer afin qu'ils soient nommés
plutôt que silencieusement omis d'une conclusion.
Un résultat propre de cet outillage est une preuve solide, pas une preuve absolue. Les deux skills le disent, de manière répétée et spécifique, et le modèle d'analyse comporte une section de limites qui n'est pas facultative.