Skip to content

Commit bd87168

Browse files
authored
Merge pull request #776 from johnnyshields/v2.x-merge-master-20251120
Merge master branch into v2.x branch
2 parents 828be53 + bfabc0a commit bd87168

File tree

6 files changed

+124
-16
lines changed

6 files changed

+124
-16
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ jobs:
3636
- 3.3
3737
- 3.4
3838
- jruby-9.4
39+
- jruby-10.0
3940
- truffleruby
4041
exclude:
4142
- os: windows-latest
4243
ruby-version: jruby-9.4
44+
- os: windows-latest
45+
ruby-version: jruby-10.0
4346
- os: windows-latest
4447
ruby-version: truffleruby
4548
runs-on: ${{ matrix.os }}

CHANGELOG.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
* [#731](https://github.com/SAML-Toolkits/ruby-saml/pull/731) Add CI coverage for Ruby 3.4. Remove CI coverage for Ruby 1.x and 2.x.
2222
* [#735](https://github.com/SAML-Toolkits/ruby-saml/pull/735) Add `Settings#sp_uuid_prefix` and deprecate `Utils#set_prefix`.
2323

24+
### 1.18.1 (Jul 29, 2025)
25+
* Fix vulnerability CVE-2025-54572 Prevent DOS due large SAML Message
26+
* Adapt tests to be able to execute signature validation sooner
27+
* CI Improvements. Support Ruby 3.4
28+
2429
### 1.18.0 (Mar 12, 2025)
2530
* [#750](https://github.com/SAML-Toolkits/ruby-saml/pull/750) Fix vulnerabilities: CVE-2025-25291, CVE-2025-25292: SAML authentication bypass via Signature Wrapping attack allowed due parser differential. Fix vulnerability: CVE-2025-25293: Potential DOS abusing of compressed messages.
2631
* [#718](https://github.com/SAML-Toolkits/ruby-saml/pull/718/) Add support to retrieve from SAMLResponse the AuthnInstant and AuthnContextClassRef values
@@ -61,7 +66,7 @@
6166
* [#614](https://github.com/SAML-Toolkits/ruby-saml/pull/614) Support :name_id_format option for IdpMetadataParser
6267
* [#611](https://github.com/SAML-Toolkits/ruby-saml/pull/611) IdpMetadataParser should always set idp_cert_multi, even when there is only one cert
6368
* [#610](https://github.com/SAML-Toolkits/ruby-saml/pull/610) New IDP sso/slo binding params which deprecate :embed_sign
64-
* [#602](https://github.com/SAML-Toolkits/ruby-saml/pull/602) Refactor the OneLogin::RubySaml::Metadata class
69+
* [#602](https://github.com/SAML-Toolkits/ruby-saml/pull/602) Refactor the RubySaml::Metadata class
6570
* [#586](https://github.com/SAML-Toolkits/ruby-saml/pull/586) Support milliseconds in cacheDuration parsing
6671
* [#585](https://github.com/SAML-Toolkits/ruby-saml/pull/585) Do not append " | " to StatusCode unnecessarily
6772
* [#607](https://github.com/SAML-Toolkits/ruby-saml/pull/607) Clean up
@@ -136,7 +141,7 @@
136141
* Updated invalid audience error message
137142

138143
### 1.7.2 (Feb 28, 2018)
139-
* [#446](https://github.com/SAML-Toolkits/ruby-saml/pull/446) Normalize text returned by OneLogin::RubySaml::Utils.element_text
144+
* [#446](https://github.com/SAML-Toolkits/ruby-saml/pull/446) Normalize text returned by RubySaml::Utils.element_text
140145

141146
### 1.7.1 (Feb 28, 2018)
142147
* [#444](https://github.com/SAML-Toolkits/ruby-saml/pull/444) Fix audience validation for empty audience restriction
@@ -266,7 +271,7 @@
266271
* [#226](https://github.com/SAML-Toolkits/ruby-saml/pull/226) Ensure IdP certificate is formatted properly
267272
* [#225](https://github.com/SAML-Toolkits/ruby-saml/pull/225) Add documentation to several methods. Fix xpath injection on xml_security.rb
268273
* [#223](https://github.com/SAML-Toolkits/ruby-saml/pull/223) Allow logging to be delegated to an arbitrary Logger
269-
* [#222](https://github.com/SAML-Toolkits/ruby-saml/pull/222) No more silent failure fetching idp metadata (OneLogin::RubySaml::HttpError raised).
274+
* [#222](https://github.com/SAML-Toolkits/ruby-saml/pull/222) No more silent failure fetching idp metadata (RubySaml::HttpError raised).
270275

271276
### 0.9.2 (Apr 28, 2015)
272277
* [#216](https://github.com/SAML-Toolkits/ruby-saml/pull/216) Add fingerprint algorithm support
@@ -314,10 +319,10 @@
314319
* [#183](https://github.com/SAML-Toolkits/ruby-saml/pull/183) Resolved a security vulnerability where string interpolation in a `REXML::XPath.first()` method call allowed for arbitrary code execution.
315320

316321
### 0.8.0 (Feb 21, 2014)
317-
**IMPORTANT**: This release changed namespace of the gem from `OneLogin::Saml` to `OneLogin::RubySaml`. Please update your implementations of the gem accordingly.
322+
**IMPORTANT**: This release changed namespace of the gem from `Saml` to `RubySaml`. Please update your implementations of the gem accordingly.
318323

319-
* [#111](https://github.com/SAML-Toolkits/ruby-saml/pull/111) `Onelogin::` is `OneLogin::`
320-
* [#108](https://github.com/SAML-Toolkits/ruby-saml/pull/108) Change namespacing from `Onelogin::Saml` to `Onelogin::Rubysaml`
324+
* [#111](https://github.com/SAML-Toolkits/ruby-saml/pull/111) `` is ``
325+
* [#108](https://github.com/SAML-Toolkits/ruby-saml/pull/108) Change namespacing from `Saml` to `Rubysaml`
321326

322327
### 0.7.3 (Feb 20, 2014)
323328
Updated gem dependencies to be compatible with Ruby 1.8.7-p374 and 1.9.3-p448. Removed unnecessary `canonix` gem dependency.

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,18 @@ Ruby SAML minor versions may introduce breaking changes. Please read
99

1010
## Vulnerability Notice
1111

12-
There are **critical vulnerabilities** affecting ruby-saml < 1.18.0 which allow
13-
SAML authentication bypass (CVE-2024-45409, CVE-2025-25291, CVE-2025-25292, CVE-2025-25293).
14-
**Please upgrade to a fixed version (1.18.0 or 2.0.0) as soon as possible.**
12+
Please note the following **critical vulnerabilities**:
13+
14+
- CVE-2025-54572 (DOS attack vector) affects version ruby-saml < 1.18.1
15+
- CVE-2024-45409, CVE-2025-25291, CVE-2025-25292, CVE-2025-25293 (SAML authentication bypass) affects ruby-saml < 1.18.0
16+
17+
**Please upgrade to a fixed version (2.0.0 or 1.18.1) as soon as possible.**
18+
19+
## Sponsors
20+
21+
Thanks to the following sponsors for securing the open source ecosystem,
22+
23+
[<img alt="84codes" src="https://avatars.githubusercontent.com/u/5353257" width="75px">](https://www.84codes.com)
1524

1625
## Overview
1726

@@ -46,7 +55,7 @@ it by email to the maintainer: [email protected]
4655
The following Ruby versions are covered by CI testing:
4756

4857
* Ruby (MRI) 3.0 to 3.4
49-
* JRuby 9.4
58+
* JRuby 9.4 to 10.0
5059
* TruffleRuby (latest)
5160

5261
Older Ruby versions are supported on the 1.x release of Ruby SAML.

UPGRADING.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ This issue is likely not critical for most IdPs, but since it is not tested, it
2626

2727
### Root "OneLogin" namespace changed to "RubySaml"
2828

29-
RubySaml version `2.0.0` changes the root namespace from `OneLogin::RubySaml::` to just `RubySaml::`.
30-
Please remove `OneLogin::` and `onelogin/` everywhere in your codebase. Aside from this namespace change,
29+
RubySaml version `2.0.0` changes the root namespace from `RubySaml::` to just `RubySaml::`.
30+
Please remove `` and `onelogin/` everywhere in your codebase. Aside from this namespace change,
3131
the class names themselves have intentionally been kept the same.
3232

3333
Note that the project folder structure has also been updated accordingly. Notably, the directory
3434
`lib/onelogin/schemas` is now `lib/ruby_saml/schemas`.
3535

36-
For backward compatibility, the alias `OneLogin = Object` has been set, so `OneLogin::RubySaml::` will still work
36+
For backward compatibility, the alias `OneLogin = Object` has been set, so `RubySaml::` will still work
3737
as before. This alias will be removed in RubySaml version `3.0.0`.
3838

3939
### Deprecation and removal of "XMLSecurity" namespace
@@ -319,7 +319,7 @@ options = {
319319
"RelayState" => raw_query_params["RelayState"],
320320
},
321321
}
322-
slo_logout_request = OneLogin::RubySaml::SloLogoutrequest.new(query_params["SAMLRequest"], settings, options)
322+
slo_logout_request = RubySaml::SloLogoutrequest.new(query_params["SAMLRequest"], settings, options)
323323
raise "Invalid Logout Request" unless slo_logout_request.is_valid?
324324
```
325325

@@ -379,4 +379,4 @@ Version `0.9` adds many new features and improvements.
379379

380380
## Upgrading from 0.7.x to 0.8.x
381381

382-
Version `0.8.x` changes the namespace of the gem from `OneLogin::Saml` to `OneLogin::RubySaml`. Please update your implementations of the gem accordingly.
382+
Version `0.8.x` changes the namespace of the gem from `Saml` to `RubySaml`. Please update your implementations of the gem accordingly.

test/response_test.rb

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class RubySamlTest < Minitest::Test
77
describe "Response" do
88
let(:settings) { RubySaml::Settings.new }
99
let(:response) { RubySaml::Response.new(response_document_without_recipient) }
10-
let(:response_without_recipient) { OneLogin::RubySaml::Response.new(signed_response_document_without_recipient) }
10+
let(:response_without_recipient) { RubySaml::Response.new(signed_response_document_without_recipient) }
1111
let(:response_without_attributes) { RubySaml::Response.new(response_document_without_attributes) }
1212
let(:response_with_multiple_attribute_statements) { RubySaml::Response.new(fixture(:response_with_multiple_attribute_statements)) }
1313
let(:response_without_reference_uri) { RubySaml::Response.new(response_document_without_reference_uri) }
@@ -1752,6 +1752,74 @@ def generate_audience_error(expected, actual)
17521752
end
17531753
end
17541754

1755+
describe "DOS attack via oversized payload" do
1756+
it "rejects oversized payloads before attempting Base64 validation" do
1757+
large_saml_response = "A" * (RubySaml::Settings::DEFAULTS[:message_max_bytesize] + 100)
1758+
1759+
assert_raises(RubySaml::ValidationError, "Encoded SAML Message exceeds #{RubySaml::Settings::DEFAULTS[:message_max_bytesize]} bytes, so was rejected") do
1760+
RubySaml::Response.new(large_saml_response)
1761+
end
1762+
end
1763+
1764+
it "rejects oversized payloads before attempting Base64 validation with custom max_bytesize" do
1765+
custom_max = 10000
1766+
large_saml_response = "A" * (custom_max + 100)
1767+
custom_settings = RubySaml::Settings.new({ message_max_bytesize: custom_max })
1768+
1769+
assert_raises(RubySaml::ValidationError, "Encoded SAML Message exceeds #{custom_max} bytes, so was rejected") do
1770+
RubySaml::Response.new(large_saml_response, settings: custom_settings)
1771+
end
1772+
end
1773+
end
1774+
1775+
describe "Zlib bomb attack" do
1776+
it "rejects Zlib bomb attacks" do
1777+
# Create a message that when inflated would be extremely large
1778+
bomb_prefix = <<~XML
1779+
<?xml version='1.0' encoding='UTF-8'?>
1780+
<samlp:Response xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' ID='_test_response_id' Version='2.0' IssueInstant='2014-07-18T01:13:06Z' Destination='http://sp.example.com/saml/acs'>
1781+
<saml:Issuer>http://idp.example.com/</saml:Issuer>
1782+
<samlp:Status><samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:Success'/></samlp:Status>
1783+
<saml:Assertion xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' ID='_test_assertion_id' IssueInstant='2014-07-18T01:13:06Z' Version='2.0'>
1784+
<saml:Issuer>http://idp.example.com/</saml:Issuer>
1785+
<saml:Subject><saml:NameID>
1786+
XML
1787+
1788+
bomb_suffix = <<~XML
1789+
</saml:NameID></saml:Subject>
1790+
</saml:Assertion>
1791+
</samlp:Response>
1792+
XML
1793+
1794+
bomb_data = bomb_prefix + 'A' * (200_000 * 1024) + bomb_suffix
1795+
bomb = Base64.strict_encode64(Zlib::Deflate.deflate(bomb_data, 9)[2..-5])
1796+
1797+
assert_raises(RubySaml::ValidationError) do
1798+
RubySaml::Response.new(bomb)
1799+
end
1800+
end
1801+
1802+
it "rejects Zlib bomb attacks with custom max_bytesize" do
1803+
custom_max = 100_000
1804+
custom_settings = RubySaml::Settings.new({:message_max_bytesize => custom_max})
1805+
1806+
bomb_prefix = <<~XML
1807+
<?xml version='1.0' encoding='UTF-8'?>
1808+
<samlp:Response xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' ID='_test' Version='2.0'>
1809+
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>http://idp.example.com/</saml:Issuer>
1810+
XML
1811+
1812+
bomb_suffix = "</samlp:Response>"
1813+
1814+
bomb_data = bomb_prefix + 'A' * (custom_max + 100) + bomb_suffix
1815+
bomb = Base64.strict_encode64(Zlib::Deflate.deflate(bomb_data, 9)[2..-5])
1816+
1817+
assert_raises(RubySaml::ValidationError, "SAML Message exceeds #{custom_max} bytes, so was rejected") do
1818+
RubySaml::Response.new(bomb, settings: custom_settings)
1819+
end
1820+
end
1821+
end
1822+
17551823
describe "signature wrapping attack with encrypted assertion" do
17561824
it "should not be valid" do
17571825
settings.private_key = ruby_saml_key_text

test/xml/decoder_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,29 @@ class XmlDecoderTest < Minitest::Test
6767
end
6868
end
6969

70+
it 'rejects oversized payloads before attempting Base64 validation' do
71+
large_saml_message = 'A' * (RubySaml::XML::Decoder::DEFAULT_MAX_BYTESIZE + 100)
72+
73+
assert_raises(RubySaml::ValidationError, "Encoded SAML Message exceeds #{RubySaml::XML::Decoder::DEFAULT_MAX_BYTESIZE} bytes, so was rejected") do
74+
# Mock to ensure base64_encoded? is never called on oversized input
75+
RubySaml::XML::Decoder.expects(:base64_encoded?).never
76+
77+
RubySaml::XML::Decoder.decode_message(large_saml_message)
78+
end
79+
end
80+
81+
it 'rejects oversized payloads before attempting Base64 validation with custom max' do
82+
custom_max = 1000
83+
large_saml_message = 'A' * (custom_max + 100)
84+
85+
assert_raises(RubySaml::ValidationError, "Encoded SAML Message exceeds #{custom_max} bytes, so was rejected") do
86+
# Mock to ensure base64_encoded? is never called on oversized input
87+
RubySaml::XML::Decoder.expects(:base64_encoded?).never
88+
89+
RubySaml::XML::Decoder.decode_message(large_saml_message, custom_max)
90+
end
91+
end
92+
7093
it "rejects Zlib bomb attacks" do
7194
# Create a message that when inflated would be extremely large
7295
bomb_prefix = <<~XML

0 commit comments

Comments
 (0)