Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions config/initializers/vips.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

# Dabble Me processes untrusted user images with libvips (CarrierWave::Vips,
# CollageGenerator, ImageProcessing::Vips). libvips marks some loaders/savers as
# "untrusted" / unfuzzed (Magick, SVG, PDF, JPEG 2000, JXL, etc.). Keep those
# disabled process-wide so crafted uploads cannot exercise them.
#
# Supported formats (JPEG, PNG, GIF, WebP, HEIC/HEIF) use trusted loaders and
# remain available. Requires libvips >= 8.13 and ruby-vips >= 2.2.1.
#
# Related: CVE-2026-66066 / GHSA-xr9x-r78c-5hrm (Active Storage path; Dabble Me
# does not use Active Storage variants, but shares the same libvips surface).

begin
require 'nokogiri'

Check notice on line 15 in config/initializers/vips.rb

View check run for this annotation

codefactor.io / CodeFactor

config/initializers/vips.rb#L15

Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. (Style/StringLiterals)
rescue LoadError
# Ensure nokogiri is loaded before vips, which also depends on libxml2.
# See https://github.com/sparklemotion/nokogiri/discussions/2746
end

require 'ruby-vips'

Check notice on line 21 in config/initializers/vips.rb

View check run for this annotation

codefactor.io / CodeFactor

config/initializers/vips.rb#L21

Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. (Style/StringLiterals)

unless Vips.respond_to?(:block_untrusted)
raise <<~ERROR.squish
libvips untrusted operations cannot be disabled. Blocking them requires
libvips 8.13+ and ruby-vips 2.2.1+. Upgrade libvips/ruby-vips before
processing untrusted image uploads.
ERROR
end

Vips.block_untrusted(true)
33 changes: 33 additions & 0 deletions spec/initializers/vips_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'libvips untrusted operation blocking' do
it 'enables block_untrusted at boot' do
expect(Vips).to respond_to(:block_untrusted)
end

it 'still loads trusted web formats' do
jpeg = Vips::Image.black(8, 8).jpegsave_buffer
png = Vips::Image.black(8, 8).pngsave_buffer
webp = Vips::Image.black(8, 8).webpsave_buffer
gif = Vips::Image.black(8, 8).gifsave_buffer

expect(Vips::Image.new_from_buffer(jpeg, '').width).to eq(8)
expect(Vips::Image.new_from_buffer(png, '').width).to eq(8)
expect(Vips::Image.new_from_buffer(webp, '').width).to eq(8)
expect(Vips::Image.new_from_buffer(gif, '').width).to eq(8)
end

it 'blocks untrusted SVG loading' do
svg = <<~SVG
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
<rect width="10" height="10"/>
</svg>
SVG

expect {
Vips::Image.new_from_buffer(svg, '')
}.to raise_error(Vips::Error)
end
end
Loading