diff --git a/Dockerfile b/Dockerfile index cdce1fec06..74533e1e00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,6 +47,8 @@ ENV RAILS_ENV=production ENV BUNDLE_WITHOUT="development:test" ENV LD_PRELOAD=/lib/libgcompat.so.0 ENV OPENSSL_CONF=/app/openssl_legacy.cnf +# CVE-2026-66066: block unfuzzed libvips loaders process-wide (puma/sidekiq/console) +ENV VIPS_BLOCK_UNTRUSTED=1 WORKDIR /app diff --git a/Gemfile b/Gemfile index 7b3ea703aa..deedc6204d 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ gem 'premailer-rails' gem 'pretender' gem 'puma', require: false gem 'rack' -gem 'rails' +gem 'rails', '~> 8.0.5' gem 'rails_autolink' gem 'rails-i18n' gem 'rotp' diff --git a/Gemfile.lock b/Gemfile.lock index f556a5ddf9..f5514fa9ac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,29 @@ GEM remote: https://rubygems.org/ specs: - actioncable (8.0.1) - actionpack (= 8.0.1) - activesupport (= 8.0.1) + actioncable (8.0.5.1) + actionpack (= 8.0.5.1) + activesupport (= 8.0.5.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.0.1) - actionpack (= 8.0.1) - activejob (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + actionmailbox (8.0.5.1) + actionpack (= 8.0.5.1) + activejob (= 8.0.5.1) + activerecord (= 8.0.5.1) + activestorage (= 8.0.5.1) + activesupport (= 8.0.5.1) mail (>= 2.8.0) - actionmailer (8.0.1) - actionpack (= 8.0.1) - actionview (= 8.0.1) - activejob (= 8.0.1) - activesupport (= 8.0.1) + actionmailer (8.0.5.1) + actionpack (= 8.0.5.1) + actionview (= 8.0.5.1) + activejob (= 8.0.5.1) + activesupport (= 8.0.5.1) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.1) - actionview (= 8.0.1) - activesupport (= 8.0.1) + actionpack (8.0.5.1) + actionview (= 8.0.5.1) + activesupport (= 8.0.5.1) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -31,35 +31,35 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.0.1) - actionpack (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + actiontext (8.0.5.1) + actionpack (= 8.0.5.1) + activerecord (= 8.0.5.1) + activestorage (= 8.0.5.1) + activesupport (= 8.0.5.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.0.1) - activesupport (= 8.0.1) + actionview (8.0.5.1) + activesupport (= 8.0.5.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.1) - activesupport (= 8.0.1) + activejob (8.0.5.1) + activesupport (= 8.0.5.1) globalid (>= 0.3.6) - activemodel (8.0.1) - activesupport (= 8.0.1) - activerecord (8.0.1) - activemodel (= 8.0.1) - activesupport (= 8.0.1) + activemodel (8.0.5.1) + activesupport (= 8.0.5.1) + activerecord (8.0.5.1) + activemodel (= 8.0.5.1) + activesupport (= 8.0.5.1) timeout (>= 0.4.0) - activestorage (8.0.1) - actionpack (= 8.0.1) - activejob (= 8.0.1) - activerecord (= 8.0.1) - activesupport (= 8.0.1) + activestorage (8.0.5.1) + actionpack (= 8.0.5.1) + activejob (= 8.0.5.1) + activerecord (= 8.0.5.1) + activesupport (= 8.0.5.1) marcel (~> 1.0) - activesupport (8.0.1) + activesupport (8.0.5.1) base64 benchmark (>= 0.3) bigdecimal @@ -321,7 +321,7 @@ GEM net-imap net-pop net-smtp - marcel (1.0.4) + marcel (1.2.1) matrix (0.4.2) method_source (1.1.0) mini_magick (4.13.2) @@ -403,20 +403,20 @@ GEM rack (>= 1.3) rackup (2.2.1) rack (>= 3) - rails (8.0.1) - actioncable (= 8.0.1) - actionmailbox (= 8.0.1) - actionmailer (= 8.0.1) - actionpack (= 8.0.1) - actiontext (= 8.0.1) - actionview (= 8.0.1) - activejob (= 8.0.1) - activemodel (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + rails (8.0.5.1) + actioncable (= 8.0.5.1) + actionmailbox (= 8.0.5.1) + actionmailer (= 8.0.5.1) + actionpack (= 8.0.5.1) + actiontext (= 8.0.5.1) + actionview (= 8.0.5.1) + activejob (= 8.0.5.1) + activemodel (= 8.0.5.1) + activerecord (= 8.0.5.1) + activestorage (= 8.0.5.1) + activesupport (= 8.0.5.1) bundler (>= 1.15.0) - railties (= 8.0.1) + railties (= 8.0.5.1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -431,13 +431,14 @@ GEM actionview (> 3.1) activesupport (> 3.1) railties (> 3.1) - railties (8.0.1) - actionpack (= 8.0.1) - activesupport (= 8.0.1) + railties (8.0.5.1) + actionpack (= 8.0.5.1) + activesupport (= 8.0.5.1) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.2.1) @@ -551,6 +552,7 @@ GEM thor (1.3.2) timeout (0.4.3) trailblazer-option (0.1.2) + tsort (0.2.0) turbo-rails (2.0.11) actionpack (>= 6.0.0) railties (>= 6.0.0) @@ -638,7 +640,7 @@ DEPENDENCIES pry-rails puma rack - rails + rails (~> 8.0.5) rails-i18n rails_autolink rotp diff --git a/config/initializers/vips_block_untrusted.rb b/config/initializers/vips_block_untrusted.rb new file mode 100644 index 0000000000..5bcd70cfd3 --- /dev/null +++ b/config/initializers/vips_block_untrusted.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# CVE-2026-66066: block libvips loaders unsafe for untrusted input. +# Covers Active Storage and first-party Vips::Image.new_from_buffer call sites. +# Requires libvips >= 8.13 and ruby-vips >= 2.2.1. +if defined?(Vips) && Vips.respond_to?(:block_untrusted) + Vips.block_untrusted(true) +else + # Fail loudly (but do not block boot) so a missing mitigation cannot be missed + # in staging/production. Matches careerplug_webhook_config.rb reporting style. + message = 'Vips.block_untrusted unavailable (libvips < 8.13 or ruby-vips < 2.2.1?) — ' \ + 'CVE-2026-66066 mitigation NOT active' + warn "WARNING: #{message}" + + unless Rails.env.local? + Rails.logger.error("[vips_block_untrusted] #{message}") + Airbrake.notify(message) + end +end