Roundup Semanal de Ruby, Rails e IA: Falhas de DNS na Gem Resolv, lemans em Open Source e RubyLLM 2.0 (23–30 de agosto de 2026)
O Ruby corrige duas vulnerabilidades de DNS na gem resolv, a Rails Foundation abre o código do harness de benchmark lemans, e o RubyLLM 2.0 separa providers de protocols.
A semana de 23 a 30 de agosto girou em torno de infraestrutura que toda aplicação Rails usa sem pensar muito: resolução de DNS, compilação de ERB e introspecção de schema. O Ruby publicou um advisory para a gem resolv, o Rails fez merge de um novo template engine HTML-aware e de uma mudança de config que quebra compatibilidade, e o AI tooling em Ruby teve sua semana mais movimentada em meses, por conta da Rails Foundation e do RubyLLM. Nada aqui exige correria, mas alguns itens merecem entrar na lista desta semana.
Ruby corrige duas falhas de resolução DNS: CVE-2026-80212 e CVE-2026-80213
O time de segurança do Ruby divulgou, em 27 de agosto, duas vulnerabilidades na gem resolv: a CVE-2026-80212, um bug de exaustão de memória, e a CVE-2026-80213, um bypass de validação de hostname. As duas afetam código que resolve um hostname que um atacante consegue influenciar — o destino de um webhook, uma URL informada pelo usuário — seja via Resolv diretamente, via resolv-replace, ou via alguma dependency que resolve nomes do mesmo jeito.
A CVE-2026-80212 permite que um atacante aponte um domínio para um name server sob seu controle e devolva respostas DNS que a lib retém sem limite; lookups repetidos fazem o processo crescer até estourar a memória. A CVE-2026-80213 é a mais grave para quem faz filtro de SSRF: ela permite que um hostname aprovado por uma allow list resolva para um nome diferente do que foi validado, desde que o hostname ultrapasse os limites de tamanho do DNS (255 octets no total, 63 por label). Validações que já rejeitam nomes acima desses limites não são afetadas.
Código de socket comum — Net::HTTP, TCPSocket — usa o resolver do sistema operacional e não é exposto, mesmo o Net::HTTP carregando a gem resolv só para suas regex de endereço IP. As versões afetadas vão de 0.3.1 e anteriores até 0.7.1; o Ruby 4.0 embarca resolv 0.7.0, o Ruby 3.4 embarca 0.7.1, e o Ruby 3.3 embarca 0.3.1. Atualize para resolv 0.7.2 (0.3.2 na série 3.3). O Ruby 3.2 está em end of life e não recebe patch dedicado — instale a 0.7.2 diretamente lá. O crédito pela descoberta é do pesquisador de segurança dalifit.
lemans: a Rails Foundation abre o código do harness por trás do Agents on Rails
Em 24 de agosto, a Rails Foundation abriu o código do lemans, o benchmark harness Ruby-native por trás do leaderboard do Agents on Rails, junto com quatro novas rodadas de modelos. O lemans substitui o Harbor, em Python, com que o time começou o projeto, e vale a pena olhar se você já quis uma ferramenta convention-over-configuration para avaliar coding agents em tarefas Rails de verdade, em vez de leaderboards genéricos.
Os quatro novos modelos contaram uma história desigual. O Qwen3.8-27B, o modelo open-weight pequeno o suficiente para rodar localmente, pontuou 48 de 63, mas levou uma mediana de 27 minutos por run — o time teve que subir o timeout de 30 para 60 minutos — com o pior recall de Rails API do grupo, 7,9%. O Terra pontuou 49 de 63 por 20 centavos de dólar por run, com mediana de 182 segundos, agora o modelo mais rápido testado. O Sonnet 5 da Anthropic ficou em 44 de 63, o pior resultado já registrado para a família, um spread bem largo em relação aos 92% do Opus 5.
Instale com gem install lemans a partir do repo ai-evals, aponte para um sandbox Daytona ou Docker local, e rode lemans run --model <provider>/<name> --task <task> --attempts 3. Qualquer provider suportado pelo RubyLLM funciona. O harness restaura test/, bin/ e config/environments/test.rb de um snapshot anterior ao run antes de avaliar, então o agent não consegue reescrever os testes pelos quais é julgado, e remove credenciais de provider de todo arquivo que escreve em disco — defesa adicionada depois que um run anterior vazou uma OpenRouter key num trajectory file publicado.
RubyLLM 2.0 separa providers de protocols
Carmine Paolino apresentou o RubyLLM 2.0 em dois posts nesta semana, começando em 27 de agosto com uma reescrita que separa providers — o serviço ao qual você se conecta — de protocols — o formato de wire que ele fala. Na versão 1.x, providers como o Mistral herdavam do OpenAI para reaproveitar código de request e depois precisavam desfazer as suposições que não se aplicavam. Na 2.0, um provider registra os protocols que suporta e escolhe um por model; o provider inteiro do Mistral agora tem cerca de 25 linhas.
A mudança que mais aplicações vão notar: o OpenAI agora usa a Responses API por padrão, já que é a única das duas que permite reasoning models usarem tools e extended thinking ao mesmo tempo. Para voltar à Chat Completions, escolha por chat com protocol: :chat_completions, ou globalmente via config.openai_protocol. O AWS Bedrock recebe o mesmo tratamento — Claude fala a Messages API da Anthropic, cinco models falam Responses, os outros quarenta e um falam Chat Completions, tudo atrás de um único host — e o RubyLLM roteia isso automaticamente, inclusive no meio de uma conversa com .with_model.
Quatro novos providers (Cohere, Ollama Cloud, ElevenLabs, Deepgram) levam o total a dezessete, e um generator ruby_llm provider-gem monta uma provider gem externa completa — git init, bundler, CI, RuboCop, specs com live-recording — para quem não quer esperar um provider chegar ao core. O RubyLLM 2.0 ainda não tinha sido lançado no momento desta escrita; trate isso como um aviso antecipado, não como um upgrade para agendar.
Herb traz um ERB engine HTML-aware para o Action View
O Rails fez merge do suporte ao Herb como uma nova implementação de ERB em 25 de agosto. O Herb faz parse de HTML e do Ruby embutido numa única syntax tree — usando o Prism para a parte de Ruby — em vez de tratar o ERB como texto opaco, como faz o Erubi, o que significa que um template que produziria HTML ou Ruby inválido falha em tempo de compilação, e não em produção no momento do render.
O ActionView::Template::Handlers::ERB::Herb foi feito como substituto drop-in, byte a byte compatível com o Erubi; o escaping continua acontecendo inteiramente no ActionView::OutputBuffer em tempo de render, sem mudança. A gem herb agora é dependency do actionview, junto com a erubi, mas ainda não existe flag de framework default — é preciso setar ActionView::Template::Handlers::ERB.erb_implementation = ActionView::Template::Handlers::ERB::Herb manualmente para testar. Um pull request de acompanhamento propondo config.action_view.html_aware_erb é esperado, com maintainers discutindo default true no Rails 8.2; apps não prontas poderiam reverter com config.load_defaults 8.2. Vale acompanhar se seu time mantém linting de ERB, já que o entendimento estrutural do Herb também alimenta seu linter, formatter e language server standalone.
Rails unifica a configuração de tabelas ignoradas no schema — e é uma mudança que quebra compatibilidade
O Rails fez merge de uma mudança de config pequena, mas genuinamente breaking, em 26 de agosto: config.active_record.schema_ignored_tables substitui tanto ActiveRecord::SchemaDumper.ignore_tables quanto config.active_record.schema_cache_ignored_tables, que antes precisavam ser setadas separadamente para excluir uma tabela tanto do schema.rb quanto do schema cache. As duas configs antigas ficam deprecated — seus readers e writers agora emitem warning e delegam para a nova — mas o merge expôs uma inconsistência real que vale checar antes de fazer upgrade.
As duas configs antigas comparavam nomes de tabela de jeitos diferentes: o SchemaDumper removia table_name_prefix/table_name_suffix antes de comparar com seus padrões de ignore, enquanto o SchemaCache comparava com o nome real no banco. Com table_name_prefix = 'omg_' e um padrão /^_/, uma tabela _rats (nome físico omg__rats) era ignorada pelo dumper e não pelo cache. Depois dessa mudança, os dois comparam contra o nome físico, então esse padrão precisa ser atualizado para pegar uma tabela com prefixo. As tabelas internas do Rails (schema_migrations, ar_internal_metadata) não são afetadas; recebem prefixo/sufixo automaticamente antes de entrar na lista de ignore. Se você usa table_name_prefix ou table_name_suffix junto com alguma das configs deprecated, revise seus padrões contra os nomes físicos das tabelas antes de subir para uma versão do Rails que inclua esse commit.
Destaque editorial: "RubyLLM 2.0: The Agentic Loop, Exposed"
O post de acompanhamento de Carmine Paolino merece os 20 minutos sozinho. No RubyLLM 1.x, o loop de chamar o model e depois rodar as tools vivia dentro de um ask fechado; na 2.0, vira verbos que você aciona — ask_later, generate, run_tools, step, complete? — e dá para rodar a partir de um background job, um turno por job, de forma que um agent sobrevive a um restart do worker e retoma das messages persistidas em vez de perder o lugar. O chat.cancel! seta uma flag que outra thread, ou outra request no Rails, aciona pelo banco de dados, sem pub/sub no Redis. O escape hatch halt() das tools da 1.x foi removido; parar o loop agora é responsabilidade de quem chama. Se você está avaliando workflows de agent em cima do ActiveJob, é o texto mais claro sobre os trade-offs que você vai achar este mês.
Ações para a semana
- Atualize a gem resolv para 0.7.2 (0.3.2 no Ruby 3.3) se algo no seu stack chama
Resolv, carregaresolv-replace, ou resolve um hostname que um atacante consegue influenciar — isso é uma CVE, não um nice-to-have. - Antes de subir para uma versão do Rails posterior a 26 de agosto, audite qualquer combinação de
table_name_prefix/table_name_suffixcomschema_cache_ignored_tablesouSchemaDumper.ignore_tables— o alvo da comparação mudou de nome lógico para nome físico da tabela. - Aponte o
lemanspara seus próprios pull requests do Rails para ver como o model que você já está pagando se sai em tarefas com a cara do Rails, em vez de confiar num leaderboard genérico. - Segure o pin do RubyLLM 2.0 até ele ser lançado, e se você usa
halt()dentro de uma tool hoje, planeje a reescrita — ele é removido na 2.0. - Se seu time mantém linting ou tooling de ERB, fique de olho no pull request de acompanhamento de
config.action_view.html_aware_erb; o Herb é opt-in por enquanto, mas caminha para virar default no Rails 8.2.
Comentários
Faça login com Google ou GitHub para comentar.