
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.
# rails-activestorage-vips-audit Uma [Agent Skill](https://agentskills.io/specification) 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. ## A vulnerabilidade | | | | :--------- | :-------------------------------------------------------------------------------------------- | | 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](https://github.com/rails/rails/security/advisories/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: 1. `activestorage` está em uma faixa de versão afetada 2. O Active Storage está em uso 3. `config.active_storage.variant_processor` resolve para `:vips` 4. A aplicação aceita uploads de usuários não confiáveis A 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. ## Instalação 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](https://github.com/vercel-labs/skills), que instala a mesma skill no Claude Code, Codex, Cursor, Copilot CLI e outros agentes: ```sh npx skills add paveg/rails-activestorage-vips-audit ``` Ou manualmente: ```sh 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. ## Uso 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: ```sh 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. ## O que ela não lhe dirá - **A versão do libvips em tempo de execução.** Ela não pode ser determinada de forma conclusiva a partir de um repositório, e isso importa: abaixo do libvips 8.13, as operações inseguras não podem ser desabilitadas de forma alguma. Em uma aplicação sem correção, isso significa que nenhuma mitigação pode funcionar; em uma corrigida, significa que o Active Storage gera erro na inicialização em vez de executar sem segurança, então uma atualização não verificada faz o deploy falhar em vez de deixar um buraco silencioso. Verifique com `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. - **Se uma mitigação está ativa.** `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. ## Resumo da remediação 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: - Defina a variável de ambiente `VIPS_BLOCK_UNTRUSTED` (libvips `>= 8.13`; nenhuma alteração de gem necessária) - Chame `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. ## Aviso legal - Use esta skill somente em repositórios que você possua ou para os quais esteja explicitamente autorizado a auditar. - Vereditos são análises estáticas de melhor esforço. Um veredito NOT AFFECTED não é prova de não exposição: variáveis de ambiente implantadas e código em outros serviços são invisíveis para uma auditoria de repositório. O libvips de runtime é relatado separadamente porque afeta a mitigação e a prontidão de implantação, não se o repositório atende às condições de exposição. - A skill não contém código de exploit e não reconstruirá a cadeia de ataque, independentemente de como uma solicitação for formulada. - Fornecida sob a [Licença MIT](https://github.com/paveg/rails-activestorage-vips-audit/blob/main/LICENSE), sem garantia de qualquer tipo. Agir com base em um relatório — atualizações, mitigações, rotação de segredos — continua sendo responsabilidade do operador. ## Fontes - [Aviso de segurança do Rails GHSA-xr9x-r78c-5hrm](https://github.com/rails/rails/security/advisories/GHSA-xr9x-r78c-5hrm) - [Ethiack — KindaRails2Shell: Rails RCE (CVE-2026-66066)](https://ethiack.com/info-hub/research/kindarails2shell-rails-rce-cve-2026-66066) - [Guias do Rails — Configuring Rails Applications](https://guides.rubyonrails.org/configuring.html) A vulnerabilidade foi encontrada e relatada de forma independente por [RyotaK](https://x.com/ryotkak) 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.