RCE dans Rails Active Storage, corrigée dans 8.1.4.1 (GHSA-f3w6-w445-fwh9)
Rails Active Storage avant 8.0.5.2 et 8.1.4.1 laisse un fichier piégé faire lire ou écrire des fichiers à ImageMagick ou FFmpeg, voire une RCE ; mettez à jour.
TL;DR
- Un fichier malveillant téléversé vers une application Rails qui traite ses pièces jointes avec ImageMagick peut permettre à un attaquant non authentifié d'écrire des fichiers arbitraires sur le serveur. L'équipe Rails a divulgué la faille le 4 novembre 2026.
- Les versions d'Active Storage antérieures à 8.0.5.2 et la série 8.1 antérieure à 8.1.4.1 sont concernées. Une seconde faille de la même série de versions laisse un nom de fichier téléversé choisir le décodeur FFmpeg ou ImageMagick appliqué au fichier.
- L'équipe Rails qualifie la faille d'écriture de fichiers de critique (CVSS v3.0 9,8) et la faille de décodeur de haute gravité (CVSS v3.1 8,8). Aucun CVE n'est attribué, et aucune des deux failles ne figure au catalogue Known Exploited Vulnerabilities (KEV) de la CISA au 4 novembre 2026.
- Mettez à jour activestorage vers 8.0.5.2 ou 8.1.4.1 maintenant, et lisez les notes de migration : le correctif embarque une politique de sécurité ImageMagick qui exige mini_magick 5.1 ou ultérieur. Voir « Comment corriger ? ».
Suis-je concerné ?
Pour la faille critique d'écriture de fichiers, GHSA-f3w6-w445-fwh9, toutes ces conditions doivent être réunies :
- Votre application traite les pièces jointes d'Active Storage avec ImageMagick. C'est
config.active_storage.variant_processor = :mini_magick, la valeur par défaut des applications surload_defaults 6.1ou antérieur. - Votre hôte exécute ImageMagick sous une politique de sécurité qui n'interdit pas déjà les codeurs concernés. Vérifiez dans votre
policy.xmlles codeursMSL,MVGet ceux qui reposent sur Ghostscript. La politique packagée par Debian 12 interdit les codeurs Ghostscript et URL, mais elle n'a aucune règleMSLet sa seule règleMVGest commentée : elle ne bloque donc pas la chaîne signalée. - Votre application accepte des téléversements de fichiers provenant d'utilisateurs non fiables.
Pour la faille de décodeur, GHSA-v924-7rp8-4mxh, toutes ces conditions doivent être réunies :
- Votre application accepte des téléversements d'utilisateurs non fiables.
- Elle analyse les pièces jointes vidéo ou audio, ce qu'Active Storage fait à l'attachement par défaut, génère des aperçus vidéo, ou traite des images avec ImageMagick.
Le chemin AviSynth de la faille de décodeur exige un FFmpeg compilé avec --enable-avisynth et le runtime AviSynthPlus. Le FFmpeg amont et les paquets Linux et Homebrew usuels ne l'activent pas. Les builds GPL distribués pour Windows et Linux depuis ffmpeg.org l'activent, et d'autres décodeurs sélectionnés par l'extension peuvent être atteints sans AviSynth.
| Branche | Versions concernées | Version corrigée |
|---|---|---|
| 8.1.x | 8.1.0 à 8.1.4 | 8.1.4.1, publiée le 2026-11-04 |
| 8.0.x | 8.0.0 à 8.0.5.1 | 8.0.5.2, publiée le 2026-11-04 |
| 7.2 et toutes les séries antérieures | Aucun correctif ne sera publié ; la série n'est plus supportée | Migrer vers 8.0.5.2 au minimum |
Les versions de sécurité de Rails ne couvrent que les séries 8.0 et 8.1, et la série 8.0 quitte le support de sécurité le 7 novembre 2026 selon la politique de maintenance. Les applications sur 7.2 ou antérieur doivent considérer cette publication comme l'échéance pour passer à une série supportée. Le gem activestorage compte 561 823 760 téléchargements sur RubyGems au 4 novembre 2026, et le gem rails 811 345 791.
Vérifiez ce que vous exécutez :
# Version in the application's Gemfile.lock
grep -m1 'activestorage (' Gemfile.lock
# Version of the installed gem
bundle info activestorage | head -1
# Which variant processor is configured (no output means the framework default)
grep -R 'variant_processor' config/
# Does your FFmpeg admit the AviSynth demuxer? (prints the flag when enabled)
ffmpeg -version | grep -i avisynth
Comment corriger ?
- Passez l'application à une version corrigée. Épinglez le gem rails sur 8.1.4.1, ou 8.0.5.2 sur la série 8.0 :
# Gemfile
gem "rails", "~> 8.1.4.1"
# then
bundle update rails
- Lisez les notes de migration avant de déployer. Les versions corrigées appliquent une politique de sécurité ImageMagick à chaque processus ImageMagick lancé par MiniMagick, ce qui exige mini_magick 5.1 ou ultérieur. Une application sur un mini_magick plus ancien lève une exception au démarrage.
- Recréez les conteneurs d'application si vous déployez en conteneurs. Tirer une nouvelle image sans recréer le conteneur en cours laisse l'ancien code en place.
- Si votre application rend du PostScript ou du PDF via ImageMagick, réautorisez le délégué
gset les codeurs qu'il utilise dans lepolicy.xmlde l'hôte, car la politique embarquée les interdit. Une politique hôte qui autorise un codeur l'emporte sur l'interdiction embarquée. - Reportez les règles de la politique embarquée dans la politique système d'ImageMagick si la politique embarquée ne peut pas atteindre votre application. C'est le cas quand l'application :
- remplace
MiniMagick.cli_envaprès le démarrage, vide l'environnement avecMiniMagick.cli_prefixou installe son propreMiniMagick::Shell; - utilise GraphicsMagick, qui ne lit pas les politiques d'ImageMagick.
- remplace
Pour les applications qui ne peuvent pas mettre à jour immédiatement, la solution de repli de l'avis est de copier les règles de la politique embarquée dans la politique système d'ImageMagick. Le fichier embarqué est activestorage/lib/active_storage/image_magick/policy.xml, et un chemin système courant est /etc/ImageMagick-7/policy.xml. Au minimum, interdisez le codeur MSL, les codeurs Ghostscript et le délégué gs :
<policy domain="coder" rights="none" pattern="MSL"/>
<policy domain="delegate" rights="none" pattern="gs"/>
<policy domain="coder" rights="none" pattern="{PS,PS2,PS3,EPS,EPS2,EPS3,EPI,EPSF,EPSI,EPT,EPT2,EPT3,PDF,AI,EPDF,PDFA,POCKETMOD,XPS,PCL}"/>
Pour la faille de décodeur, les applications qui ne peuvent pas mettre à jour peuvent empêcher Active Storage d'exécuter FFmpeg sur les fichiers téléversés, adapté de l'avis. Cela ferme le chemin FFmpeg, mais pas les décodeurs d'ImageMagick sélectionnés par l'extension :
# config/environments/production.rb
config.active_storage.previewers =
ActiveStorage.previewers - [ActiveStorage::Previewer::VideoPreviewer]
config.active_storage.analyzers =
ActiveStorage.analyzers - [ActiveStorage::Analyzer::VideoAnalyzer, ActiveStorage::Analyzer::AudioAnalyzer]
Quelle est la cause racine ?
Deux propriétés d'outils externes ont rencontré deux valeurs par défaut d'Active Storage.
Pour la faille critique, ImageMagick choisit un codeur d'après le contenu du fichier qu'on lui donne. Certains codeurs agissent ensuite sur des fichiers nommés à l'intérieur de l'image plutôt que sur l'image elle-même. Le codeur MSL est l'interface de script XML d'ImageMagick : il lit et écrit des fichiers nommés à l'intérieur de l'image. D'autres lisent ou suppriment un fichier autre que l'image, ou transmettent le fichier au délégué Ghostscript.
Active Storage n'imposait aucune contrainte aux codeurs d'ImageMagick avant cette version. L'analyseur ImageMagick s'exécute dès qu'un fichier est attaché, et attacher le téléversement suffit donc pour atteindre un codeur. Aucun appel à variant, preview ou analyze n'est requis.
Le commit de correctif pour 8.1, 468aa9a93fc98f5476b6821770f4ccfcb7f7d328 (« Ship an ImageMagick security policy for every MiniMagick process », 3 novembre 2026), ajoute la politique et la câble via l'engine :
# activestorage/lib/active_storage/engine.rb at 8.1.4.1
if ActiveStorage::MINIMAGICK_AVAILABLE && !ActiveStorage::MINIMAGICK_UNSECURABLE
ActiveStorage::ImageMagick.apply_policy
end
Pour la faille de haute gravité, ActiveStorage::Blob#open écrit un blob dans un fichier temporaire dont le nom porte l'extension du nom de fichier téléversé, puis transmet ce chemin à ffprobe, ffmpeg et ImageMagick. La ligne vulnérable, dans 8.1.4 :
# activestorage/app/models/active_storage/blob.rb, line 324 at v8.1.4
def open(tmpdir: nil, &block)
service.open(
key,
checksum: checksum,
verify: !composed,
name: [ "ActiveStorage-#{id}-", filename.extension_with_delimiter ],
tmpdir: tmpdir,
&block
)
end
filename.extension_with_delimiter relève du choix de la personne qui téléverse. FFmpeg choisit son demuxer AviSynth sur la seule extension .avs, et ImageMagick sélectionne codeurs et délégués depuis l'extension de la même façon.
Comment la faille est-elle exploitée ?
Pour la faille critique :
- L'attaquant téléverse un fichier malveillant vers une application concernée. Le fichier doit seulement être attaché ; l'analyseur s'exécute à l'attachement, et aucun appel à variant, preview ou
analyzen'est requis. - ImageMagick choisit un codeur d'après le contenu du fichier. Dans la chaîne signalée, un SVG téléversé a atteint le codeur de script
MSL, qui lit et écrit les fichiers que son script nomme. - Le codeur écrit sur le serveur des fichiers choisis par l'attaquant. Quand les pièces jointes sont stockées avec le service Disk, la même classe de codeurs peut lire des fichiers arbitraires lisibles par le processus applicatif.
- Ces fichiers incluent typiquement
secret_key_baseet des identifiants de systèmes externes. L'avis précise que cela peut permettre une élévation vers l'exécution de code à distance ou un mouvement latéral, et qu'une chaîne d'attaque précise a été signalée mais que d'autres peuvent exister.
Pour la faille de haute gravité, les tests du correctif documentent les noms de l'attaque :
- L'attaquant téléverse un fichier nommé
attack.avsen déclarant son type de contenuvideo/mp4. Le blob est analysé à l'attachement, et Active Storage transmet le fichier temporaire àffprobeetffmpeg. - Parce que le nom du fichier temporaire se termine par
.avs, un FFmpeg compilé avec le support AviSynth évalue le fichier comme un script AviSynth. - Le script importe des fichiers lisibles par le processus applicatif et les divulgue via l'image d'aperçu. Il peut aussi charger une bibliothèque native téléversée par l'attaquant, ce qui pourrait conduire à l'exécution de code à distance dans le processus FFmpeg.
- D'autres décodeurs que FFmpeg ou ImageMagick choisissent d'après l'extension peuvent être atteints sans AviSynth. Les tests couvrent aussi
evil.mp4, un téléversement déclaréimage/pngdont le contenu est une playlist qui nomme un fichier local. Son extension.mp4pourrait conduire ImageMagick à le déléguer à FFmpeg.
Comment l'attaque se déroule-t-elle ?
Un téléversement non authentifié atteint un outil externe qui prend ses instructions dans le téléversement, et l'outil agit ensuite sur des fichiers que l'attaquant nomme.
lance l'analyseur"] B --> C["ImageMagick choisit un codeur
d'après le contenu du fichier"] C --> D["Aucune politique ne contraint
les codeurs"] D --> E["Le codeur MSL agit sur des fichiers
nommés dans l'image"] E --> F["Écriture de fichiers arbitraires
sur le serveur"] F --> G["Service Disk : lecture de fichiers secrets,
élévation possible vers l'exécution de code"]
Que peut faire un attaquant ?
La faille critique peut donner à une personne qui téléverse, sans authentification, des écritures de fichiers arbitraires sur le serveur. L'équipe Rails lui attribue un score CVSS v3.0 de 9,8, CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. Trois conditions doivent être réunies : un processeur de variantes ImageMagick, une politique hôte qui n'interdit pas déjà les codeurs concernés, et des téléversements d'utilisateurs non fiables.
Le codeur MSL et les codeurs similaires qui écrivent des fichiers lisent aussi des fichiers quand les pièces jointes utilisent le service Disk, ce qui expose typiquement secret_key_base, la clé maîtresse et des identifiants de systèmes externes. L'équipe Rails indique que cela peut permettre une élévation vers l'exécution de code à distance ou un mouvement latéral vers ces systèmes.
La faille de haute gravité peut divulguer des fichiers lisibles par le processus applicatif via une image d'aperçu générée. L'équipe Rails lui attribue un score CVSS v3.1 de 8,8, CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H, qui suppose un attaquant disposant de faibles privilèges sur l'application.
Pour la faille de haute gravité, la divulgation de fichiers comme l'exécution de code exigent un FFmpeg compilé avec le support AviSynth. D'autres décodeurs choisis d'après l'extension peuvent être atteints sans AviSynth, mais l'avis ne leur attribue aucun impact précis.
Pourquoi le correctif fonctionne-t-il ?
Le correctif de la faille critique contraint chaque processus ImageMagick lancé par MiniMagick, et pas seulement celui de l'analyseur. La politique embarquée interdit :
- le codeur
MSLet les codeurs qui lisent ou suppriment des fichiers autres que l'image ; - les références locales et distantes, et l'affichage à l'écran ;
- tous les codeurs appuyés sur Ghostscript, avec le délégué
gs; - l'indirection
@filename.
Comme ImageMagick applique chaque policy.xml de son chemin de recherche, la politique embarquée s'ajoute à celle de l'hôte au lieu de la remplacer.
Le correctif de la faille de haute gravité empêche le nom de fichier téléversé de choisir le décodeur. Le fichier temporaire ne garde l'extension que si Marcel associe cette extension au type de contenu enregistré du blob, et n'en porte aucune sinon. Le commit de correctif, 72136ff39153bc8d63ecbc899993848eb3d6573e (« Active Storage: tempfile extension must match the blob's content type »), remplace l'extension brute par un choix validé :
--- a/activestorage/app/models/active_storage/blob.rb
+++ b/activestorage/app/models/active_storage/blob.rb
@@ -321,7 +322,7 @@ def open(tmpdir: nil, &block)
key,
checksum: checksum,
verify: !composed,
- name: [ "ActiveStorage-#{id}-", filename.extension_with_delimiter ],
+ name: [ "ActiveStorage-#{id}-", tempfile_extension ],
tmpdir: tmpdir,
&block
)
@@ -360,6 +361,25 @@ def service
end
private
+ # The extension is there for tools that cannot tell the type from the bytes (316d87e4: ImageMagick
+ # needs it for an SVG with no XML declaration), but some tools choose a decoder on it alone: FFmpeg
+ # runs a `.avs` file as an AviSynth script. So the uploaded extension is kept only when it denotes
+ # the blob's media type.
+ def tempfile_extension
+ extension = filename.extension_with_delimiter
+ return "" if extension.blank?
+
+ type_for_extension = Marcel::MimeType.for(name: filename.to_s)
+ return "" if type_for_extension == Marcel::MimeType::BINARY || type_for_extension != media_type
+
+ extension
+ end
+
+ # Marcel answers in canonical lowercase, so drop parameters and case before comparing.
+ def media_type
+ content_type.to_s.split(";").first.to_s.strip.downcase
+ end
+
def compute_checksum_in_chunks(io)
Les fichiers dont l'extension téléversée contredit le type de contenu restent traités, et l'outil externe détecte alors leur format d'après leur contenu. Un téléversement de formulaire dont le fichier temporaire Rack échoue au même contrôle est copié vers un fichier temporaire correctement nommé avant traitement.
Le correctif de la faille critique réduit la surface d'attaque sans prouver qu'aucune autre chaîne n'existe. L'avis indique qu'une chaîne d'attaque a été signalée et que l'équipe Rails ne suppose pas qu'elle soit la seule. Certaines applications ne reçoivent jamais la politique embarquée ; voir « Comment corriger ? ».
Comment savoir si j'ai été compromis ?
Rails ne publie aucun indicateur pour ces deux failles. Une tentative échouée peut ne laisser aucune trace.
Pour la faille critique, passez en revue le serveur à la recherche de fichiers que l'utilisateur applicatif n'a pas créés, en particulier dans les chemins servis par le web. Si votre application remplissait les conditions concernées et stockait ses pièces jointes avec le service Disk avant votre mise à jour, considérez chaque secret lisible par le processus applicatif comme exposé. L'avis nomme secret_key_base, la clé maîtresse, tout ce que contient config/credentials.yml.enc, les identifiants de stockage et de base de données, ainsi que les jetons de services tiers.
Pour la faille de haute gravité, une application qui exécutait un FFmpeg avec le support AviSynth doit considérer chaque secret lisible par le processus applicatif comme exposé, pour le même ensemble. Changer secret_key_base expire les sessions actives et invalide les cookies signés et chiffrés, les identifiants globaux signés et les URL Active Storage.
Chronologie
Le correctif de nommage de fichier temporaire a été rédigé 53 jours avant la sortie des versions coordonnées.
- 2026-09-12 : Le correctif d'extension de fichier temporaire a été rédigé dans la branche 8.1 (commit 72136ff3).
- 2026-11-03 : Le correctif de politique de sécurité ImageMagick a été committé (commit 468aa9a9, 20:10 UTC).
- 2026-11-04 : Rails 8.0.5.2 (02:31 UTC) et 8.1.4.1 (02:46 UTC) ont été publiées sur GitHub.
- 2026-11-04 : L'annonce coordonnée des 21 problèmes corrigés a été publiée sur oss-security (02:58 UTC).
- 2026-11-04 : Les deux avis ont été rendus publics (GHSA-v924-7rp8-4mxh à 03:02 UTC, GHSA-f3w6-w445-fwh9 à 03:09 UTC).
FAQ
Le correctif change-t-il le démarrage de mon application ?
Une application dont le processeur de variantes est :mini_magick exige mini_magick 5.1 ou ultérieur, car l'application de la politique le réclame. Avec un mini_magick plus ancien, l'application lève une exception au démarrage. Les applications utilisant libvips, la valeur par défaut depuis load_defaults 7.0, ne sont pas concernées par cette exigence.
J'utilise libvips. Suis-je concerné ?
La faille critique d'écriture de fichiers exige le processeur de variantes ImageMagick, donc une application libvips n'en est pas concernée. La faille de décodeur s'applique indépendamment du processeur : les pièces jointes vidéo et audio sont analysées avec ffprobe à l'attachement par défaut, et le correctif de nommage de fichier temporaire couvre ce chemin.
Mon application rend du PDF ou du PostScript via ImageMagick. Qu'en est-il ?
La politique embarquée interdit tous les codeurs appuyés sur Ghostscript et le délégué gs. Votre application doit réautoriser le délégué et les codeurs qu'elle utilise dans le policy.xml de l'hôte, faute de quoi le rendu cessera de fonctionner après la mise à jour.
Que sont les 19 autres problèmes de sécurité de cette version ?
La même version corrige trois autres problèmes de haute gravité : un contournement de Strong Parameters dans Parameters#each_key, une usurpation d'adresse IP dans Action Dispatch RemoteIp (8.1 uniquement) et un déni de service dans safe_constantize. Les 16 autres sont de gravité moyenne ou faible, dont des correctifs de cross-site scripting (XSS), de déni de service et de gestion de session. L'annonce oss-security relie chaque avis.
Pourquoi aucun CVE n'est-il attribué ?
L'équipe Rails a publié les deux failles comme des avis de sécurité de dépôt, et aucune ne porte d'identifiant CVE au 4 novembre 2026. Aucune ne figure non plus à cette date dans la GitHub Advisory Database, si bien que les outils d'analyse de dépendances qui s'appuient sur les CVE ou sur cette base peuvent ne pas les signaler. Vérifiez directement votre Gemfile.lock face aux versions corrigées.
Ma série Rails est 7.2 ou antérieure. Que faire ?
Aucun correctif ne sera publié pour votre série, car elle n'est plus supportée. Migrez vers 8.0.5.2 au minimum, et planifiez de quitter 8.0 : son support de sécurité prend fin le 7 novembre 2026.
Repérez vos applications Rails exposées avant qu'un attaquant ne le fasse
Les applications Rails qui acceptent des téléversements d'utilisateurs non fiables sont à corriger en premier. Le Web Agentic Deep Scan d'Ostorlab analyse vos applications web et vos API à la recherche de vulnérabilités, ce qui vous aide à repérer les points de téléversement exposés à des utilisateurs non fiables.
Références
- GHSA-f3w6-w445-fwh9, avis de sécurité Rails, « Possible arbitrary file write and read in Active Storage image analysis » : https://github.com/rails/rails/security/advisories/GHSA-f3w6-w445-fwh9 (consulté le 4 novembre 2026)
- GHSA-v924-7rp8-4mxh, avis de sécurité Rails, « Possible arbitrary file read and remote code execution in Active Storage video previews, analysis and image processing » : https://github.com/rails/rails/security/advisories/GHSA-v924-7rp8-4mxh (consulté le 4 novembre 2026)
- Annonce des versions de sécurité Rails, 21 problèmes corrigés dans 8.0.5.2 et 8.1.4.1 : https://www.openwall.com/lists/oss-security/2026/11/04/2 (consulté le 4 novembre 2026)
- Commit de correctif 468aa9a93fc98f5476b6821770f4ccfcb7f7d328, « Ship an ImageMagick security policy for every MiniMagick process » (8.1) : https://github.com/rails/rails/commit/468aa9a93fc98f5476b6821770f4ccfcb7f7d328 (consulté le 4 novembre 2026)
- Commit de correctif 72136ff39153bc8d63ecbc899993848eb3d6573e, « Active Storage: tempfile extension must match the blob's content type » (8.1) : https://github.com/rails/rails/commit/72136ff39153bc8d63ecbc899993848eb3d6573e (consulté le 4 novembre 2026)
- Commit de correctif ea8c40121ce53a3d0255cd4eb6d13bfe3bc01776, « Ship an ImageMagick security policy for every MiniMagick process » (8.0) : https://github.com/rails/rails/commit/ea8c40121ce53a3d0255cd4eb6d13bfe3bc01776 (consulté le 4 novembre 2026)
- Commit de correctif 8106938fb0a595f11006dd1497cd409e27d7d636, « Active Storage: tempfile extension must match the blob's content type » (8.0) : https://github.com/rails/rails/commit/8106938fb0a595f11006dd1497cd409e27d7d636 (consulté le 4 novembre 2026)
- CHANGELOG d'Active Storage à v8.1.4.1 : https://github.com/rails/rails/blob/v8.1.4.1/activestorage/CHANGELOG.md (consulté le 4 novembre 2026)
- Version Rails 8.0.5.2 : https://github.com/rails/rails/releases/tag/v8.0.5.2 (consultée le 4 novembre 2026)
- Version Rails 8.1.4.1 : https://github.com/rails/rails/releases/tag/v8.1.4.1 (consultée le 4 novembre 2026)
- Téléchargements du gem activestorage : https://rubygems.org/gems/activestorage (consultés le 4 novembre 2026)
- Politique de maintenance de Rails : https://rubyonrails.org/maintenance (consultée le 4 novembre 2026)
- Documentation de la politique de sécurité ImageMagick : https://imagemagick.org/security-policy/ (consultée le 4 novembre 2026)
- policy.xml d'ImageMagick packagé par Debian 12 : https://sources.debian.org/src/imagemagick/8:6.9.11.60+dfsg-1.6+deb12u11/config/policy.xml/ (consulté le 4 novembre 2026)