Backport Redmine::Helpers::URL#uri_with_link_safe_scheme? from r21161 to 4.2-stable (#38806).

git-svn-id: https://svn.redmine.org/redmine/branches/4.2-stable@22300 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Go MAEDA
2023-09-18 06:28:42 +00:00
parent 4567650f1e
commit 83fdb7e481
2 changed files with 56 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ require 'uri'
module Redmine
module Helpers
module URL
# safe for resources fetched without user interaction?
def uri_with_safe_scheme?(uri, schemes = ['http', 'https', 'ftp', 'mailto', nil])
# URLs relative to the current document or document root (without a protocol
# separator, should be harmless
@@ -32,6 +33,20 @@ module Redmine
rescue URI::Error
false
end
# safe to render links to given uri?
def uri_with_link_safe_scheme?(uri)
# regexp adapted from Sanitize (we need to catch even invalid protocol specs)
return true unless uri =~ /\A\s*([^\/#]*?)(?:\:|&#0*58|&#x0*3a)/i
# absolute scheme
scheme = $1.downcase
return false unless /\A[a-z][a-z0-9\+\.\-]*\z/.match?(scheme) # RFC 3986
# To support Ruby 2.4, we use `none? {|obj| ... }` instead of
# `none?(pattern)` in 4.2-stable branch.
%w(data javascript vbscript).none? {|v| v == scheme}
end
end
end
end

View File

@@ -33,4 +33,45 @@ class URLTest < ActiveSupport::TestCase
assert_not uri_with_safe_scheme?("httpx://example.com/")
assert_not uri_with_safe_scheme?("mailto:root@")
end
LINK_SAFE_URIS = [
"http://example.com/",
"https://example.com/",
"ftp://example.com/",
"foo://example.org",
"mailto:foo@example.org",
" http://example.com/",
"",
"/javascript:alert(\'filename\')",
]
def test_uri_with_link_safe_scheme_should_recognize_safe_uris
LINK_SAFE_URIS.each do |uri|
assert uri_with_link_safe_scheme?(uri), "'#{uri}' should be safe"
end
end
LINK_UNSAFE_URIS = [
"javascript:alert(\'XSS\');",
"javascript :alert(\'XSS\');",
"javascript: alert(\'XSS\');",
"javascript : alert(\'XSS\');",
":javascript:alert(\'XSS\');",
"javascript&#58;",
"javascript&#0058;",
"javascript&#x3A;",
"javascript&#x003A;",
"java\0script:alert(\"XSS\")",
"java\script:alert(\"XSS\")",
" \x0e javascript:alert(\'XSS\');",
"data:image/png;base64,foobar",
"vbscript:foobar",
"data:text/html;base64,foobar",
]
def test_uri_with_link_safe_scheme_should_recognize_unsafe_uris
LINK_UNSAFE_URIS.each do |uri|
assert_not uri_with_link_safe_scheme?(uri), "'#{uri}' should not be safe"
end
end
end