Hi,
At first glance this looks good.
The 2 not-affected are not reported in the security tracker, maybe you
can do it directly, with your rationale (streaming proxy module not
present).
Did you try to manually run a rails app and see if everything's good? We
have some notes at
https://lts-team.pages.debian.net/wiki/TestSuites/rails.html , redmine
can be a good candidate, when available for the target rails version.
Cheers!
Sylvain Beucler
Debian LTS Team
On 05/10/2026 03:52, Simon Quigley wrote:
Bookworm rails is 2:6.1.7.10+dfsg-1~deb12u2. I put the seven no-dsa CVEs
whose code is in Rails 6.1, and CVE-2026-66066 for applications that set
the variant processor to :vips, into one update,
2:6.1.7.10+dfsg-1~deb12u3. The commits are pushed to Salsa and a debdiff
is attached.
These are the ones I fixed:
- CVE-2026-66066: the vips processor calls vips_block_untrusted_set
before it opens an upload. ruby-vips 2.1.4 does not bind that function,
so the patch attaches it. BMP variants then raise Vips::Error. The
MiniMagick default is unchanged.
- CVE-2026-33168: a blank HTML attribute name skipped escaping. Blank
names are now skipped.
- CVE-2026-33169: delimiting a long digit string was quadratic. The
default path walks the digits. 1,234,567 still looks the same.
- CVE-2026-33170: formatting an unsafe SafeBuffer with % marked the
result safe. It stays unsafe.
- CVE-2026-33173: a direct upload could set analyzed and identified and
skip content-type detection. Those keys are dropped. Rails 6.1 has no
composed flag.
- CVE-2026-33176: number helpers expanded scientific notation through
BigDecimal. number_to_currency("1E1000") stays "$1E1000".
- CVE-2026-33195: a disk key with ../ could leave the storage root. That
now raises InvalidKeyError.
- CVE-2026-33202: delete_prefixed passed the prefix to Dir.glob. Glob
metacharacters are escaped.
CVE-2026-66066 closes #1143080. Each of the other seven closes #1132035.
That bug was closed by 2:7.2.3.1+dfsg-1.
CVE-2026-33174 and CVE-2026-33658 stay out of this update. I asked the
Security Team to mark those two not-affected. There is no 6.1 commit for
either of them.
CVE-2026-33174 is the proxy holding a whole Range in one string. On 7.2,
streaming.rb calls download_chunk, which does file.read(range.size).
bytes=0- on a large file is that allocation. Bookworm's blob proxy and
representation proxy do not have that file, and they do not read the
Range header. ActiveStorage::BaseController#stream writes the file out
in 5MB chunks. download_chunk exists, but outside the tests the only
caller reads the first 4KB. The disk service URL does honor Range,
through Rack::Files in ruby-rack 2.2.22, in 8KB reads. That is not this
bug.
CVE-2026-33658 is the same proxy appending every range in the header
onto one buffer. Bookworm's proxy never calls
Rack::Utils.get_byte_ranges. Rack::Files on the disk URL does accept
several ranges, and it walks them in 8KB reads instead of building one
string. There is no streaming_max_ranges method to patch.
CVE-2026-66066 is in this update. The Bookworm default
stays :mini_magick, and the engine still loads image_analyzer.rb only.
Setting the variant processor to :vips used to leave libvips's unfuzzed
loaders on, because ruby-vips 2.1.4 never calls vips_block_untrusted_set
and image_processing 1.10.3 never calls block_untrusted. The patch
attaches that symbol from libvips 8.14.1 and calls it when the vips
processor runs. The 7.2 file calls Vips.block_untrusted and raises at
boot on 2.1.4, so this is not that file.
I built this in a Bookworm schroot. The packaged test suite was 344 runs
and 0 failures on each of five runs, with 24 and 26 skips on the first
two. autopkgtest newapp and gem2deb-test-runner both passed. That runner
only executes Active Job, so on bookworm-testing I ran the same
behavioral script as Trixie, first on 2:6.1.7.10+dfsg-1~deb12u2 and then
on this package.
On the archive package the seven were VULNERABLE in the same way as
Trixie. A blank attribute name emitted the onerror value. Delimiting
50,000 ones took 6.2 seconds. An unsafe SafeBuffer became html_safe
after %. number_to_currency("1E1000") expanded to about 1,300
characters. path_for reached /etc/passwd. delete_prefixed with a [1]
prefix deleted the plain sibling and left the bracket key. Direct upload
metadata was not filtered. CVE-2026-33174 and CVE-2026-33658 were
NOT_AFFECTED: there is no streaming proxy. With the variant processor
set to :vips, before the 66066 patch, an SVG and a BMP both opened.
On this package those seven reported FIXED. 1,234,567 and $1,234.50 were
unchanged, the Indian delimiter pattern still worked, a blank attribute
value was kept, a safe buffer stayed safe, and avatars/123/photo stayed
inside the root. Traversal, blank, and null-byte keys were rejected. The
bracket key was the only one the glob prefix deleted. analyzed and
identified were dropped and the caption stayed. 50,000 ones took 0.005
seconds. CVE-2026-33174 and CVE-2026-33658 were NOT_AFFECTED again.
After the 66066 patch I ran the variants through
ImageProcessingTransformer#transform. PNG, JPEG, WebP, TIFF, and GIF
each resized to 8x6 as PNG, JPEG, and WebP. SVG, PPM, BMP, ICO, PSD, and
PDF were blocked. Saving a PNG variant as BMP was blocked. Twenty-five
PNG variants in one process still resized. The MiniMagick default still
resized a PNG and left svgload available.
Salsa pipeline: https://salsa.debian.org/ruby-team/rails/-/
pipelines/1183706
Debusine work request: https://debusine.debian.net/debian/developers/
work-request/1418454/
Feedback is welcome. If nothing showstopping is raised, I plan to upload
this on the morning of Thursday, October 8th, 2026, or whenever the
Trixie DSA is issued for this set of CVEs, whatever comes later.
Best regards,
Simon Quigley
[email protected]