345 lines
11 KiB
Ruby
345 lines
11 KiB
Ruby
require 'test_helper'
|
|
require 'hanami/utils'
|
|
require 'hanami/utils/escape'
|
|
|
|
describe Hanami::Utils::Escape do
|
|
let(:mod) { Hanami::Utils::Escape }
|
|
|
|
describe '.html' do
|
|
TEST_ENCODINGS.each do |encoding|
|
|
describe "#{ encoding }" do
|
|
it "doesn't escape safe string" do
|
|
input = Hanami::Utils::Escape::SafeString.new('&')
|
|
result = mod.html(input.encode(encoding))
|
|
result.must_equal '&'
|
|
end
|
|
|
|
it "escapes nil" do
|
|
result = mod.html(nil)
|
|
result.must_equal ''
|
|
end
|
|
|
|
it "escapes 'test'" do
|
|
result = mod.html('test'.encode(encoding))
|
|
result.must_equal 'test'
|
|
end
|
|
|
|
it "escapes '&'" do
|
|
result = mod.html('&'.encode(encoding))
|
|
result.must_equal '&'
|
|
end
|
|
|
|
it "escapes '<'" do
|
|
result = mod.html('<'.encode(encoding))
|
|
result.must_equal '<'
|
|
end
|
|
|
|
it "escapes '>'" do
|
|
result = mod.html('>'.encode(encoding))
|
|
result.must_equal '>'
|
|
end
|
|
|
|
it %(escapes '"') do
|
|
result = mod.html('"'.encode(encoding))
|
|
result.must_equal '"'
|
|
end
|
|
|
|
it %(escapes "'") do
|
|
result = mod.html("'".encode(encoding))
|
|
result.must_equal '''
|
|
end
|
|
|
|
it "escapes '/'" do
|
|
result = mod.html('/'.encode(encoding))
|
|
result.must_equal '/'
|
|
end
|
|
|
|
it "escapes '<script>'" do
|
|
result = mod.html('<script>'.encode(encoding))
|
|
result.must_equal '<script>'
|
|
end
|
|
|
|
it "escapes '<scr<script>ipt>'" do
|
|
result = mod.html('<scr<script>ipt>'.encode(encoding))
|
|
result.must_equal '<scr<script>ipt>'
|
|
end
|
|
|
|
it "escapes '<script>'" do
|
|
result = mod.html('<script>'.encode(encoding))
|
|
result.must_equal '&lt;script&gt;'
|
|
end
|
|
|
|
it %(escapes '""><script>xss(5)</script>') do
|
|
result = mod.html('""><script>xss(5)</script>'.encode(encoding))
|
|
result.must_equal '""><script>xss(5)</script>'
|
|
end
|
|
|
|
it %(escapes '><script>xss(6)</script>') do
|
|
result = mod.html('><script>xss(6)</script>'.encode(encoding))
|
|
result.must_equal '><script>xss(6)</script>'
|
|
end
|
|
|
|
it %(escapes '# onmouseover="xss(7)" ') do
|
|
result = mod.html('# onmouseover="xss(7)" '.encode(encoding))
|
|
result.must_equal '# onmouseover="xss(7)" '
|
|
end
|
|
|
|
it %(escapes '/" onerror="xss(9)">') do
|
|
result = mod.html('/" onerror="xss(9)">'.encode(encoding))
|
|
result.must_equal '/" onerror="xss(9)">'
|
|
end
|
|
|
|
it %(escapes '/ onerror="xss(10)"') do
|
|
result = mod.html('/ onerror="xss(10)"'.encode(encoding))
|
|
result.must_equal '/ onerror="xss(10)"'
|
|
end
|
|
|
|
it %(escapes '<<script>xss(14);//<</script>') do
|
|
result = mod.html('<<script>xss(14);//<</script>'.encode(encoding))
|
|
result.must_equal '<<script>xss(14);//<</script>'
|
|
end
|
|
end
|
|
end
|
|
|
|
it "escapes word with different encoding" do
|
|
skip "There is no ASCII-8BIT encoding" unless Encoding.name_list.include?('ASCII-8BIT')
|
|
|
|
# 'тест' means test in russian
|
|
string = 'тест'.force_encoding('ASCII-8BIT')
|
|
encoding = string.encoding
|
|
|
|
result = mod.html(string)
|
|
result.must_equal 'тест'
|
|
result.encoding.must_equal Encoding::UTF_8
|
|
|
|
string.encoding.must_equal encoding
|
|
end
|
|
end
|
|
|
|
describe '.html_attribute' do
|
|
TEST_ENCODINGS.each do |encoding|
|
|
describe "#{ encoding }" do
|
|
it "doesn't escape safe string" do
|
|
input = Hanami::Utils::Escape::SafeString.new('&')
|
|
result = mod.html_attribute(input.encode(encoding))
|
|
result.must_equal '&'
|
|
end
|
|
|
|
it "escapes nil" do
|
|
result = mod.html_attribute(nil)
|
|
result.must_equal ''
|
|
end
|
|
|
|
it "escapes 'test'" do
|
|
result = mod.html_attribute('test'.encode(encoding))
|
|
result.must_equal 'test'
|
|
end
|
|
|
|
it "escapes '&'" do
|
|
result = mod.html_attribute('&'.encode(encoding))
|
|
result.must_equal '&'
|
|
end
|
|
|
|
it "escapes '<'" do
|
|
result = mod.html_attribute('<'.encode(encoding))
|
|
result.must_equal '<'
|
|
end
|
|
|
|
it "escapes '>'" do
|
|
result = mod.html_attribute('>'.encode(encoding))
|
|
result.must_equal '>'
|
|
end
|
|
|
|
it %(escapes '"') do
|
|
result = mod.html_attribute('"'.encode(encoding))
|
|
result.must_equal '"'
|
|
end
|
|
|
|
it %(escapes "'") do
|
|
result = mod.html_attribute("'".encode(encoding))
|
|
result.must_equal '''
|
|
end
|
|
|
|
it "escapes '/'" do
|
|
result = mod.html_attribute('/'.encode(encoding))
|
|
result.must_equal '/'
|
|
end
|
|
|
|
it "escapes '<script>'" do
|
|
result = mod.html_attribute('<script>'.encode(encoding))
|
|
result.must_equal '<script>'
|
|
end
|
|
|
|
it "escapes '<scr<script>ipt>'" do
|
|
result = mod.html_attribute('<scr<script>ipt>'.encode(encoding))
|
|
result.must_equal '<scr<script>ipt>'
|
|
end
|
|
|
|
it "escapes '<script>'" do
|
|
result = mod.html_attribute('<script>'.encode(encoding))
|
|
result.must_equal '&lt;script&gt;'
|
|
end
|
|
|
|
it %(escapes '""><script>xss(5)</script>') do
|
|
result = mod.html_attribute('""><script>xss(5)</script>'.encode(encoding))
|
|
result.must_equal '""><script>xss(5)</script>'
|
|
end
|
|
|
|
it %(escapes '><script>xss(6)</script>') do
|
|
result = mod.html_attribute('><script>xss(6)</script>'.encode(encoding))
|
|
result.must_equal '><script>xss(6)</script>'
|
|
end
|
|
|
|
it %(escapes '# onmouseover="xss(7)" ') do
|
|
result = mod.html_attribute('# onmouseover="xss(7)" '.encode(encoding))
|
|
result.must_equal '# onmouseover="xss(7)" '
|
|
end
|
|
|
|
it %(escapes '/" onerror="xss(9)">') do
|
|
result = mod.html_attribute('/" onerror="xss(9)">'.encode(encoding))
|
|
result.must_equal '/" onerror="xss(9)">'
|
|
end
|
|
|
|
it %(escapes '/ onerror="xss(10)"') do
|
|
result = mod.html_attribute('/ onerror="xss(10)"'.encode(encoding))
|
|
result.must_equal '/ onerror="xss(10)"'
|
|
end
|
|
|
|
it %(escapes '<<script>xss(14);//<</script>') do
|
|
result = mod.html_attribute('<<script>xss(14);//<</script>'.encode(encoding))
|
|
result.must_equal '<<script>xss(14);//<</script>'
|
|
end
|
|
end
|
|
end # tests with encodings
|
|
|
|
TEST_INVALID_CHARS.each do |char, entity|
|
|
it "escapes '#{ char }'" do
|
|
result = mod.html_attribute(char)
|
|
result.must_equal "&#x#{ TEST_REPLACEMENT_CHAR };"
|
|
end
|
|
end
|
|
|
|
it "escapes tab" do
|
|
result = mod.html_attribute("\t")
|
|
result.must_equal "	"
|
|
end
|
|
|
|
it "escapes return carriage" do
|
|
result = mod.html_attribute("\r")
|
|
result.must_equal "
"
|
|
end
|
|
|
|
it "escapes new line" do
|
|
result = mod.html_attribute("\n")
|
|
result.must_equal "
"
|
|
end
|
|
|
|
it "escapes unicode char" do
|
|
result = mod.html_attribute("Ā")
|
|
result.must_equal 'Ā'
|
|
end
|
|
|
|
it "doesn't escape ','" do
|
|
result = mod.html_attribute(",")
|
|
result.must_equal ','
|
|
end
|
|
|
|
it "doesn't escape '.'" do
|
|
result = mod.html_attribute(".")
|
|
result.must_equal '.'
|
|
end
|
|
|
|
it "doesn't escape '-'" do
|
|
result = mod.html_attribute("-")
|
|
result.must_equal '-'
|
|
end
|
|
|
|
it "doesn't escape '_'" do
|
|
result = mod.html_attribute("_")
|
|
result.must_equal '_'
|
|
end
|
|
|
|
TEST_HTML_ENTITIES.each do |char, entity|
|
|
test_name = Hanami::Utils.jruby? ? char.ord : char
|
|
|
|
it "escapes #{ test_name }" do
|
|
result = mod.html_attribute(char)
|
|
result.must_equal "&#{ entity };"
|
|
end
|
|
end
|
|
end # .html_attribute
|
|
|
|
describe '.url' do
|
|
TEST_ENCODINGS.each do |encoding|
|
|
describe "#{ encoding }" do
|
|
it "doesn't escape safe string" do
|
|
input = Hanami::Utils::Escape::SafeString.new('javascript:alert(0);')
|
|
result = mod.url(input.encode(encoding))
|
|
result.must_equal 'javascript:alert(0);'
|
|
end
|
|
|
|
it "escapes nil" do
|
|
result = mod.url(nil)
|
|
result.must_equal ''
|
|
end
|
|
|
|
it "escapes 'test'" do
|
|
result = mod.url('test'.encode(encoding))
|
|
result.must_equal ''
|
|
end
|
|
|
|
it "escapes 'http://hanamirb.org'" do
|
|
result = mod.url('http://hanamirb.org'.encode(encoding))
|
|
result.must_equal 'http://hanamirb.org'
|
|
end
|
|
|
|
it "escapes 'https://hanamirb.org'" do
|
|
result = mod.url('https://hanamirb.org'.encode(encoding))
|
|
result.must_equal 'https://hanamirb.org'
|
|
end
|
|
|
|
it "escapes 'https://hanamirb.org#introduction'" do
|
|
result = mod.url('https://hanamirb.org#introduction'.encode(encoding))
|
|
result.must_equal 'https://hanamirb.org#introduction'
|
|
end
|
|
|
|
it "escapes 'https://hanamirb.org/guides/index.html'" do
|
|
result = mod.url('https://hanamirb.org/guides/index.html'.encode(encoding))
|
|
result.must_equal 'https://hanamirb.org/guides/index.html'
|
|
end
|
|
|
|
it "escapes 'mailto:user@example.com'" do
|
|
result = mod.url('mailto:user@example.com'.encode(encoding))
|
|
result.must_equal 'mailto:user@example.com'
|
|
end
|
|
|
|
it "escapes 'mailto:user@example.com?Subject=Hello'" do
|
|
result = mod.url('mailto:user@example.com?Subject=Hello'.encode(encoding))
|
|
result.must_equal 'mailto:user@example.com?Subject=Hello'
|
|
end
|
|
|
|
it "escapes 'javascript:alert(1);'" do
|
|
result = mod.url('javascript:alert(1);'.encode(encoding))
|
|
result.must_equal ''
|
|
end
|
|
|
|
# See https://github.com/mzsanford/twitter-text-rb/commit/cffce8e60b7557e9945fc0e8b4383e5a66b1558f
|
|
it %(escapes 'http://x.xx/@"style="color:pink"onmouseover=alert(1)//') do
|
|
result = mod.url('http://x.xx/@"style="color:pink"onmouseover=alert(1)//'.encode(encoding))
|
|
result.must_equal 'http://x.xx/@'
|
|
end
|
|
|
|
it %{escapes 'http://x.xx/("style="color:red"onmouseover="alert(1)'} do
|
|
result = mod.url('http://x.xx/("style="color:red"onmouseover="alert(1)'.encode(encoding))
|
|
result.must_equal 'http://x.xx/('
|
|
end
|
|
|
|
it %(escapes 'http://x.xx/@%22style=%22color:pink%22onmouseover=alert(1)//') do
|
|
result = mod.url('http://x.xx/@%22style=%22color:pink%22onmouseover=alert(1)//'.encode(encoding))
|
|
result.must_equal 'http://x.xx/@'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|