Skip to content

Commit

Permalink
[bug fix] Dynamic links get broken in send_email (#1380)
Browse files Browse the repository at this point in the history
  • Loading branch information
3 people authored Jan 25, 2023
1 parent fe18115 commit b43d050
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/models/concerns/dynamic_attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def parse_dynamic_attribute(value, context = {})

def attribute_value_string(attribute)
value = public_send(attribute.to_sym)

# decoding special characters that action text encoded
value = Addressable::URI.unencode(value.to_s) if value.is_a? ActionText::RichText

# Deep copy of non-enumerable column like string-type would get passed and the evaluated value would get reflected as change.
value.is_a?(Enumerable) ? JSON.generate(value) : value.to_s.dup
end
Expand Down
4 changes: 3 additions & 1 deletion app/models/concerns/safe_executable_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ class SafeExecutableValidator < ActiveModel::EachValidator
SPLIT_DELIMITERS = ['(', ')', /\s/, '.', /\n/, /(?<!\:)\:(?!\:)/, '#{', '}', '=>', '"', '\'']

def validate_each(record,attribute,value)
keywords = value.to_s.split(Regexp.union(SPLIT_DELIMITERS)).reject(&:blank?)
# decode and unescape string before checking for blacklisted kwywords
keywords = CGI.unescapeHTML(Addressable::URI.unencode(value.to_s)).split(Regexp.union(SPLIT_DELIMITERS)).reject(&:blank?)
blacklisted_keywords_in_attribute = keywords & (BLACKLISTED_KEYWORDS - (options[:skip_keywords] || []))

unless blacklisted_keywords_in_attribute.empty?
record.errors.add(attribute, "contains disallowed keyword: #{blacklisted_keywords_in_attribute.to_s}. Please refactor #{attribute} accordingly")
end
Expand Down
18 changes: 17 additions & 1 deletion test/models/concerns/dynamic_attribute_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def initialize(test_column: nil)
assert_equal safe_instance.test_column_evaluated, 'Test 2'
end


test 'should raise invalid record error dynamic field contains unsafe string' do
unsafe_instance = @dummy_class.new(test_column: "Test \#{User.destroy_all}")
refute unsafe_instance.valid?
Expand All @@ -41,6 +40,16 @@ def initialize(test_column: nil)
end
end

test 'should raise invalid record error if dynamic field contains encoded unsafe string' do
unsafe_instance = @dummy_class.new(test_column: "&lt;%=%20eval%20%1+2%20%&gt;")
refute unsafe_instance.valid?
assert_no_difference "User.all.size" do
assert_raises ActiveRecord::RecordInvalid do
unsafe_instance.test_column_evaluated
end
end
end

test 'should support erb syntax' do
api_resource_test = api_resources(:user)
erb_syntax = '<% food = "Ice cream" %>'\
Expand Down Expand Up @@ -106,4 +115,11 @@ def initialize(test_column: nil)
safe_instance = @dummy_class.new(test_column: { test_key: "<%= 1 + 1 %> and \#{2 + 2}" })
assert_equal safe_instance.test_column_evaluated, { test_key: "2 and 4" }.to_json
end

test 'should unescape html and decode uri-encoded characters' do
safe_instance = @dummy_class.new(test_column: ActionText::RichText.new(body: '<a href="<%= 2 and 4 %>">'))
# action text encoded and escaped special characters
assert_equal "<div class=\"trix-content\">\n <a href=\"&lt;%=%202%20and%204%20%&gt;\"></a>\n</div>\n", safe_instance.test_column.to_s
assert_equal "<div class=\"trix-content\">\n <a href=\"4\"></a>\n</div>\n", safe_instance.test_column_evaluated
end
end

0 comments on commit b43d050

Please sign in to comment.