diff options
author | Robert Speicher <robert@gitlab.com> | 2017-05-02 17:36:26 +0300 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2017-05-04 18:03:58 +0300 |
commit | 45d295052b95828c307e2d662e400885bac05da6 (patch) | |
tree | 6c400fe68f6e9f2a489efbfd35caa85902043440 /lib | |
parent | 2177cc511f4c34904f3e7f54f8c9e872ffff0cfa (diff) |
Merge branch 'bvl-validate-urls-in-markdown-using-uri' into 'security'
Add correct `rel` attributes to external links when rendering markdown
See merge request !2086
Diffstat (limited to 'lib')
-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 |