FIX: prevent double escaping of URL

FIX: prevent double escaping of URL

diff --git a/lib/onebox/helpers.rb b/lib/onebox/helpers.rb
index e1eaa68..69d3c96 100644
--- a/lib/onebox/helpers.rb
+++ b/lib/onebox/helpers.rb
@@ -188,7 +188,8 @@ module Onebox
       src
     end
 
-    RFC_3986_URI_REGEX = /^(?<scheme>([^:\/?#]+):)?(?<authority>\/\/([^\/?#]*))?(?<path>[^?#]*)(\?(?<query>[^#]*))?(#(?<fragment>.*))?$/
+    RFC_3986_URI_REGEX ||= /^(?<scheme>([^:\/?#]+):)?(?<authority>\/\/([^\/?#]*))?(?<path>[^?#]*)(\?(?<query>[^#]*))?(#(?<fragment>.*))?$/
+    DOUBLE_ESCAPED_REGEXP ||= /%25([0-9a-f]{2})/i
 
     # Percent-encodes a URI query parameter per RFC3986 - https://tools.ietf.org/html/rfc3986
     def self.uri_query_encode(query_string)
@@ -219,6 +220,7 @@ module Onebox
       # URI::parse and URI::Generic.build don't like paths encoded with CGI.escape
       # URI.escape does not change / to %2F and : to %3A like CGI.escape
       encoded += URI.escape(parts[:path]) unless parts[:path].nil?
+      encoded.gsub!(DOUBLE_ESCAPED_REGEXP, '%\1')
 
       # each query parameter
       if !parts[:query].nil?
diff --git a/spec/lib/onebox/helpers_spec.rb b/spec/lib/onebox/helpers_spec.rb
index 04efaa6..04aae13 100644
--- a/spec/lib/onebox/helpers_spec.rb
+++ b/spec/lib/onebox/helpers_spec.rb
@@ -89,5 +89,6 @@ RSpec.describe Onebox::Helpers do
     it { expect(described_class.uri_encode("http://example.com/index&<script>alert('XSS');</script>")).to eq("http://example.com/index&%3Cscript%3Ealert('XSS');%3C/script%3E") }
     it { expect(described_class.uri_encode("http://example.com/index.html?message=<script>alert('XSS');</script>")).to eq("http://example.com/index.html?message=%3Cscript%3Ealert%28%27XSS%27%29%3B%3C%2Fscript%3E") }
     it { expect(described_class.uri_encode("http://example.com/index.php/<IFRAME SRC=source.com onload='alert(document.cookie)'></IFRAME>")).to eq("http://example.com/index.php/%3CIFRAME%20SRC=source.com%20onload='alert(document.cookie)'%3E%3C/IFRAME%3E") }
+    it { expect(described_class.uri_encode("https://en.wiktionary.org/wiki/greengrocer%27s_apostrophe")).to eq("https://en.wiktionary.org/wiki/greengrocer%27s_apostrophe") }
   end
 end

GitHub sha: ce35d518

This commit has been mentioned on Discourse Meta. There might be relevant details there: