Sinatra vulnerable to Reflected File Download attack
Description
Sinatra is a domain-specific language for creating web applications in Ruby. An issue was discovered in Sinatra 2.0 before 2.2.3 and 3.0 before 3.0.4. An application is vulnerable to a reflected file download (RFD) attack that sets the Content-Disposition header of a response when the filename is derived from user-supplied input. Version 2.2.3 and 3.0.4 contain patches for this issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Sinatra versions before 2.2.3 and 3.0.4 are vulnerable to reflected file download (RFD) attacks via user-supplied filenames in the Content-Disposition header.
Vulnerability
Sinatra, a Ruby web application DSL, is vulnerable to a reflected file download (RFD) attack in versions 2.0 before 2.2.3 and 3.0 before 3.0.4. The issue arises when the Content-Disposition header of a response is set with a filename derived from user-supplied input without proper sanitization. This allows an attacker to control the filename and extension of a downloaded file [1][2].
Exploitation
An attacker can exploit this by crafting a malicious link or form submission that triggers a response where the Content-Disposition header includes a filename such as malicious.bat or malicious.exe. When the victim clicks the link, the browser downloads the file with the attacker-controlled extension. The attack requires user interaction (e.g., clicking a link) and does not require authentication, as it can be triggered from any page that interacts with the vulnerable Sinatra application [2][3].
Impact
Successful exploitation could lead to arbitrary code execution on the victim's system if the downloaded file is opened. For example, a .bat file on Windows could execute commands, or a .jar file could run Java code. The impact is limited by the user's action of opening the file, but it can lead to full compromise of the client machine [2][3].
Mitigation
Sinatra has addressed this vulnerability in versions 2.2.3 and 3.0.4. Users should upgrade to these patched versions or later. No workaround is available; updating the gem is the recommended action [1][2][3].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
sinatraRubyGems | >= 3.0, < 3.0.4 | 3.0.4 |
sinatraRubyGems | >= 2.0.0, < 2.2.3 | 2.2.3 |
Affected products
4- ghsa-coords3 versions
>= 3.0, < 3.0.4+ 2 more
- (no CPE)range: >= 3.0, < 3.0.4
- (no CPE)range: < 0.10.14-5.el8_7.2.alma
- (no CPE)range: < 0.10.14-5.el8_7.2.alma
- sinatra/sinatrav5Range: >= 3.0, < 3.0.4
Patches
1ea8fc9495a35escape filename in the Content-Disposition header
2 files changed · +20 −1
lib/sinatra/base.rb+8 −1 modified@@ -396,13 +396,20 @@ def content_type(type = nil, params = {}) response['Content-Type'] = mime_type end + # https://html.spec.whatwg.org/#multipart-form-data + MULTIPART_FORM_DATA_REPLACEMENT_TABLE = { + '"' => '%22', + "\r" => '%0D', + "\n" => '%0A' + }.freeze + # Set the Content-Disposition to "attachment" with the specified filename, # instructing the user agents to prompt to save. def attachment(filename = nil, disposition = :attachment) response['Content-Disposition'] = disposition.to_s.dup return unless filename - params = format('; filename="%s"', File.basename(filename)) + params = format('; filename="%s"', File.basename(filename).gsub(/["\r\n]/, MULTIPART_FORM_DATA_REPLACEMENT_TABLE)) response['Content-Disposition'] << params ext = File.extname(filename) content_type(ext) unless response['Content-Type'] || ext.empty?
test/helpers_test.rb+12 −0 modified@@ -781,6 +781,18 @@ def attachment_app(filename=nil) assert_equal '<sinatra></sinatra>', body end + it 'escapes filename in the Content-Disposition header according to the multipart form data spec in WHATWG living standard' do + mock_app do + get('/attachment') do + attachment "test.xml\";\r\next=.txt" + response.write("<sinatra></sinatra>") + end + end + + get '/attachment' + assert_equal 'attachment; filename="test.xml%22;%0D%0Aext=.txt"', response['Content-Disposition'] + assert_equal '<sinatra></sinatra>', body + end end describe 'send_file' do
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-2x8x-jmrp-phxwghsaADVISORY
- github.com/advisories/GHSA-8x94-hmjh-97hqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-45442ghsaADVISORY
- github.com/rubysec/ruby-advisory-db/blob/master/gems/sinatra/CVE-2022-45442.ymlghsaWEB
- github.com/sinatra/sinatra/commit/ea8fc9495a350f7551b39e3025bfcd06f49f363bghsaWEB
- github.com/sinatra/sinatra/security/advisories/GHSA-2x8x-jmrp-phxwghsaWEB
- lists.debian.org/debian-lts-announce/2023/01/msg00005.htmlghsamailing-listWEB
- lists.debian.org/debian-lts-announce/2024/09/msg00020.htmlghsaWEB
- www.blackhat.com/docs/eu-14/materials/eu-14-Hafif-Reflected-File-Download-A-New-Web-Attack-Vector.pdfghsaWEB
News mentions
0No linked articles in our index yet.