
Habilidade de agente que audita uma base de código Rails para a CVE-2026-66066 (KindaRails2Shell) — leitura arbitrária de arquivos / RCE no Active Storage + libvips, verificando versões do Rails e do libvips e mitigações de block-untrusted.
Uma Agent Skill que audita repositórios Ruby on Rails quanto à exposição a CVE-2026-66066 (KindaRails2Shell) — a vulnerabilidade do Active Storage de processamento de variantes com libvips que permite leitura arbitrária de arquivos e, em uma aplicação Rails, execução remota de código.
A skill é um auditor de configuração e um auxílio de remediação. Ela não contém código de exploit e não descreve a cadeia de ataque.
| CVE | CVE-2026-66066 |
| Gravidade | Crítica, CVSS 9.5 |
| Pacote | activestorage (RubyGems) |
| Afetadas | < 7.2.3.2, >= 8.0 < 8.0.5.1, >= 8.1 < 8.1.3.1 |
| Corrigidas | 7.2.3.2, 8.0.5.1, 8.1.3.1 |
| Aviso | GHSA-xr9x-r78c-5hrm |
O libvips lê e grava formatos por meio de operações, algumas das quais ele marca como unfuzzed — inseguras para conteúdo não confiável. O Active Storage não as desabilitava, então um atacante que consiga enviar um arquivo manipulado pode alcançá-las.
Uma aplicação está exposta somente quando todas as quatro condições são verdadeiras:
activestorage está em uma faixa de versão afetadaconfig.active_storage.variant_processor resolve para :vipsA condição 3 é a discriminante. A faixa afetada < 7.2.3.2 inclui todas as versões Rails 6.x, mas o 6.x usa :mini_magick por padrão, portanto o 6.x está exposto somente sob uma configuração não padrão, e versões anteriores à 6.0 não possuem configuração variant_processor alguma. O Rails 7.0 e posteriores usam :vips por padrão via config.load_defaults 7.0, motivo pelo qual a configuração comum está exposta. O Rails 8.1 também aceita :disabled, o que torna a condição 3 falsa.
Como plugin do Claude Code, por meio do marketplace incluído neste repositório:
/plugin marketplace add paveg/rails-activestorage-vips-audit
/plugin install rails-activestorage-vips-audit@paveg-skills
Com a CLI skills, que instala a mesma skill no Claude Code, Codex, Cursor, Copilot CLI e outros agentes:
npx skills add paveg/rails-activestorage-vips-audit
Ou manualmente:
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/ funciona como um local entre runtimes para Codex, Copilot CLI e Gemini CLI. Nada na skill depende de onde ela está instalada — não há caminhos absolutos, e collect-evidence.sh resolve tudo em relação à raiz da aplicação para a qual é apontado.
A skill tem dois modos, e ambos aceitam múltiplos caminhos de aplicação.
report <app>... # read-only audit, one verdict per application
fix <app>... # applies remediation on a branch; never commits or pushes unprompted
Instalada como plugin, cada modo também é um comando, portanto o modo não precisa ser digitado como argumento:
/rails-activestorage-vips-audit:report path/to/app another/app
/rails-activestorage-vips-audit:fix path/to/app
Os comandos são pontos de entrada para você, não para o agente: eles são marcados para que o Claude nunca os acione por conta própria. O Claude ainda invoca a skill em si quando uma solicitação corresponde a ela, por isso fix não pode ser iniciado sem que um humano o solicite.
report é o padrão. fix exige antes um veredito de report para a mesma aplicação, pois a remediação correta depende dele — Rails 6.x, 7.0.x e 7.1.x não possuem correção na mesma série, então nesses casos fix aplica a mitigação provisória e informa que uma atualização do framework é necessária, em vez de tentar fazê-la.
A coleta de evidências também pode ser executada de forma isolada:
skills/rails-activestorage-vips-audit/scripts/collect-evidence.sh path/to/app another/app
O script coleta fatos e, deliberadamente, não contém lógica de veredito. Passe a raiz de uma aplicação, não a raiz indiferenciada de um monorepo. Para um monorepo, passe cada diretório Rails implantável com seu próprio Gemfile.lock e config/application.rb como um argumento separado. O coletor exclui essas raízes de aplicação aninhadas do fluxo de evidências de um pai, mantendo raízes de lockfile aninhadas que podem ser engines montadas ou path dependencies.
vips --version onde a aplicação é executada. Os relatórios mantêm isso em prontidão de runtime e remediação, em vez de tornar o veredito de exposição condicional.VIPS_BLOCK_UNTRUSTED em um Dockerfile não prova que o ambiente implantado a define. A skill limita tais constatações a "mitigação provisória presente, atualização ainda necessária" e nunca permite que uma delas produza um veredito limpo.Atualize para 7.2.3.2, 8.0.5.1 ou 8.1.3.1, de acordo com a sua série. Confirme o libvips de runtime >= 8.13 e ruby-vips >= 2.2.1 primeiro: onde ruby-vips está instalado, o Active Storage corrigido gera erro na inicialização a menos que ambos sejam atendidos, e essa verificação também se aplica a aplicações :mini_magick.
Mitigações provisórias, nenhuma das quais substitui a atualização:
VIPS_BLOCK_UNTRUSTED (libvips >= 8.13; nenhuma alteração de gem necessária)Vips.block_untrusted(true) a partir de um initializer (ruby-vips >= 2.2.1, além de libvips >= 8.13)Em ruby-vips < 2.2.1, o caminho do initializer chama um método que ainda não existe; portanto, atualize a gem primeiro ou use o caminho da variável de ambiente, que não depende dela.
Se uma aplicação esteve exposta, considere todo segredo legível pelo processo da aplicação como comprometido e faça a rotação: secret_key_base, a master key, credenciais do serviço do Active Storage, credenciais do banco de dados e tokens de terceiros.
Um WAF não é uma mitigação aqui. Se ele consegue ver o payload depende do serviço de armazenamento e do método de upload, portanto sua eficácia depende demais da configuração para que se possa confiar nela.
A vulnerabilidade foi encontrada e relatada de forma independente por RyotaK da GMO Flatt Security e por uma equipe da Ethiack composta por André Baptista, Bruno Mendes e Castilho, e foi divulgada em coordenação com os mantenedores do Rails.