Skip to content

Commit 4483651

Browse files
committed
Handle too long dates passed to DateTime.parse
Since Ruby 3.0.3, this method raises an ArgumentError with a different message from the invalid date message, as mitigation for CVE-2021-41817. https://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/ Example: ArgumentError: string length (150) exceeds the limit 128 In this case we should just return nil, like when the date itself is invalid.
1 parent 6e5db59 commit 4483651

File tree

4 files changed

+37
-20
lines changed

4 files changed

+37
-20
lines changed

lib/mail/elements/received_element.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def to_s(*args)
2727
def datetime_for(received)
2828
::DateTime.parse("#{received.date} #{received.time}")
2929
rescue ArgumentError => e
30-
raise e unless e.message == 'invalid date'
30+
raise unless e.message =~ /\A(invalid date|string length \(\d+\) exceeds the limit \d+)\z/
3131
warn "WARNING: Invalid date field for received element (#{received.date} #{received.time}): #{e.class}: #{e.message}"
3232
nil
3333
end

lib/mail/fields/common_date_field.rb

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,30 @@
44

55
module Mail
66
class CommonDateField < NamedStructuredField #:nodoc:
7-
def self.singular?
8-
true
9-
end
7+
class << self
8+
def singular?
9+
true
10+
end
11+
12+
def normalize_datetime(string)
13+
if Utilities.blank?(string)
14+
datetime = ::DateTime.now
15+
else
16+
stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
17+
datetime = parse_date_time(stripped)
18+
end
1019

11-
def self.normalize_datetime(string)
12-
if Utilities.blank?(string)
13-
datetime = ::DateTime.now
14-
else
15-
stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
16-
begin
17-
datetime = ::DateTime.parse(stripped)
18-
rescue ArgumentError => e
19-
raise unless 'invalid date' == e.message
20+
if datetime
21+
datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
22+
else
23+
string
2024
end
2125
end
2226

23-
if datetime
24-
datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
25-
else
26-
string
27+
def parse_date_time(string)
28+
::DateTime.parse(string)
29+
rescue ArgumentError => e
30+
raise unless e.message =~ /\A(invalid date|string length \(\d+\) exceeds the limit \d+)\z/
2731
end
2832
end
2933

@@ -33,9 +37,7 @@ def initialize(value = nil, charset = nil)
3337

3438
# Returns a date time object of the parsed date
3539
def date_time
36-
::DateTime.parse("#{element.date_string} #{element.time_string}")
37-
rescue ArgumentError => e
38-
raise e unless e.message == 'invalid date'
40+
self.class.parse_date_time("#{element.date_string} #{element.time_string}")
3941
end
4042

4143
def default

spec/mail/fields/date_field_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,11 @@
6666
field = Mail::DateField.new("12 Aug 2009 30:00:02 GMT")
6767
expect(field.date_time).to be_nil
6868
end
69+
70+
it "should handle too long invalid date" do
71+
# field = Mail::DateField.new("12 Aug 2009 30:00:02 GMT")
72+
field = Mail::DateField.new("Wed, 23 Jan 2019 30:51:32 -0500")
73+
expect(field.date_time).to be_nil
74+
end
6975
end
7076
end

spec/mail/fields/received_field_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,13 @@
5555
expect(t.date_time).to eq nil
5656
expect(t.formatted_date).to eq nil
5757
end
58+
59+
it "should handle too long invalid date" do
60+
t = Mail::ReceivedField.new("mail.example.com (192.168.1.1) by mail.example.com with (esmtp) id (qid) for <[email protected]>; Mon, (envelope-from <[email protected] ([email protected])>) 29 Jul 2013 23:12:46 +0900")
61+
62+
expect(t.name).to eq "Received"
63+
expect(t.info).to eq "mail.example.com (192.168.1.1) by mail.example.com with (esmtp) id (qid) for <[email protected]>"
64+
expect(t.date_time).to eq nil
65+
expect(t.formatted_date).to eq nil
66+
end
5867
end

0 commit comments

Comments
 (0)