diff options
author | Robert Speicher <robert@gitlab.com> | 2017-05-02 22:25:58 +0000 |
---|---|---|
committer | Bob Van Landuyt <bob@gitlab.com> | 2017-05-10 16:44:20 +0200 |
commit | da13d1af3ecfdf124d63c5cf53aca6cac8a9f36d (patch) | |
tree | b35444a3ade5da3ca2258c81568937635880d3c9 /lib/banzai | |
parent | 99996b6bc7c13e7e7f871919942907b380d4b58c (diff) | |
download | gitlab-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.rb | 36 |
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 |