-
-
Notifications
You must be signed in to change notification settings - Fork 236
Expand file tree
/
Copy pathCVE-2026-44587.yml
More file actions
80 lines (69 loc) · 2.9 KB
/
Copy pathCVE-2026-44587.yml
File metadata and controls
80 lines (69 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
---
gem: carrierwave
cve: 2026-44587
ghsa: 7g26-2qgj-chfg
url: https://www.cve.org/CVERecord?id=CVE-2026-44587
title: CarrierWave has a denylisted_content_type bypass via
Unescaped Regex Metacharacters
date: 2026-05-27
description: |
### Summary
CarrierWave's content_type_denylist check fails to escape regex
metacharacters in string entries, causing the denylist to silently
not match the content types it is intended to block.
**Note**: CarrierWave is aware `#content_type_denylist is deprecated
for the security reason`, but it still used by developers, and the
problem here isn't denylist allows any filetype, and thats not a
vulnerability in carrierwave, its an implementation problem in
developers using CarrierWave, the problem is its denylist entries
are interpolated directly into a regex without `Regexp.quote` or
anchoring. The denylist is still useful when developers want to
ban specific content types but allow everything else.
### Details
In `lib/carrierwave/uploader/content_type_denylist.rb:57`, string
denylist entries are interpolated directly into a regex without
`Regexp.quote` or anchoring:
```ruby
def denylisted_content_type?(denylist, content_type)
Array(denylist).any? { |item| content_type =~ /#{item}/ }
end
The entry "image/svg+xml" becomes the regex /image\/svg+xml/ where +
is a quantifier meaning "one or more g", not a literal +. This
regex never matches the real MIME type "image/svg+xml" which contains
a literal +. This is inconsistent with the allowlist implementation
at lib/carrierwave/uploader/content_type_allowlist.rb:53-57, which
correctly applies both Regexp.quote and a \A anchor:
rubydef allowlisted_content_type?(allowlist, content_type)
Array(allowlist).any? do |item|
item = Regexp.quote(item) if item.class != Regexp
content_type =~ /\A#{item}/
end
end
```
Other affected MIME types include `application/xhtml+xml` and any
type containing regex metacharacters.
Fix: Apply Regexp.quote for string entries and anchor with \A,
matching the existing allowlist implementation:
```
rubydef denylisted_content_type?(denylist, content_type)
Array(denylist).any? do |item|
item = Regexp.quote(item) if item.class != Regexp
content_type =~ /\A#{item}/
end
end
```
### Impact
Any application that uses content_type_denylist to block image/svg+xml
— the most common use case, specifically to prevent stored XSS — is
silently unprotected.
cvss_v3: 4.7
patched_versions:
- "~> 2.2.7"
- ">= 3.1.3"
related:
url:
- https://www.cve.org/CVERecord?id=CVE-2026-44587
- https://github.com/carrierwaveuploader/carrierwave/releases
- https://github.com/carrierwaveuploader/carrierwave/commit/21221cc6e260633f7da78c6133a88666a5529d27
- https://github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-7g26-2qgj-chfg
- https://github.com/advisories/GHSA-7g26-2qgj-chfg