summaryrefslogtreecommitdiff
path: root/lib/banzai
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2017-05-02 22:25:58 +0000
committerBob Van Landuyt <bob@gitlab.com>2017-05-10 16:44:20 +0200
commitda13d1af3ecfdf124d63c5cf53aca6cac8a9f36d (patch)
treeb35444a3ade5da3ca2258c81568937635880d3c9 /lib/banzai
parent99996b6bc7c13e7e7f871919942907b380d4b58c (diff)
downloadgitlab-ce-da13d1af3ecfdf124d63c5cf53aca6cac8a9f36d.tar.gz
Merge branch 'bvl-security-9-1-validate-urls-in-markdown-using-uri'
(security-9-1) Add correct `rel` attributes to external links when rendering markdown See merge request !2097
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/external_link_filter.rb36
1 files changed, 18 insertions, 18 deletions
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index d67d466bce8..7d15a0f6d44 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -2,16 +2,17 @@ module Banzai
module Filter
# HTML Filter to modify the attributes of external links
class ExternalLinkFilter < HTML::Pipeline::Filter
+ SCHEMES = ['http', 'https', nil].freeze
+
def call
links.each do |node|
- href = href_to_lowercase_scheme(node["href"].to_s)
+ uri = uri(node['href'].to_s)
+ next unless uri
- unless node["href"].to_s == href
- node.set_attribute('href', href)
- end
+ node.set_attribute('href', uri.to_s)
- if href =~ %r{\A(https?:)?//[^/]} && external_url?(href)
- node.set_attribute('rel', 'nofollow noreferrer')
+ if SCHEMES.include?(uri.scheme) && external_url?(uri)
+ node.set_attribute('rel', 'nofollow noreferrer noopener')
node.set_attribute('target', '_blank')
end
end
@@ -21,27 +22,26 @@ module Banzai
private
+ def uri(href)
+ URI.parse(href)
+ rescue URI::InvalidURIError
+ nil
+ end
+
def links
query = 'descendant-or-self::a[@href and not(@href = "")]'
doc.xpath(query)
end
- def href_to_lowercase_scheme(href)
- scheme_match = href.match(/\A(\w+):\/\//)
-
- if scheme_match
- scheme_match.to_s.downcase + scheme_match.post_match
- else
- href
- end
- end
+ def external_url?(uri)
+ # Relative URLs miss a hostname
+ return false unless uri.hostname
- def external_url?(url)
- !url.start_with?(internal_url)
+ uri.hostname != internal_url.hostname
end
def internal_url
- @internal_url ||= Gitlab.config.gitlab.url
+ @internal_url ||= URI.parse(Gitlab.config.gitlab.url)
end
end
end