| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- 'use strict'
- const test = require('tape')
- const fastURI = require('..')
- const MALFORMED_SCHEME_ERROR = 'URI scheme is malformed.'
- const malformedSchemes = [
- '%2f%2fevil.example:/pwn',
- '%u002f%u002fevil.example:/pwn',
- '%0d%0aSet-Cookie:%20sid=attacker:/p',
- 'foo%3Abar:value',
- 'foo%2Fbar:value',
- '1http://example.com/',
- 'foo_bar:value',
- 'éxample:value',
- 'Kttp://example.com/',
- 'ſcheme:value'
- ]
- test('parse validates the decoded scheme against RFC 3986', (t) => {
- const validSchemes = [
- ['a:value', 'a'],
- ['HTTP://example.com/', 'http'],
- ['a1+.-:value', 'a1+.-'],
- ['%4Aavascript:alert(1)', 'javascript'],
- ['foo%2Bbar:value', 'foo+bar'],
- ['%u006Aavascript:1', 'javascript'],
- ['ht%74ps://example.com/', 'https']
- ]
- for (const [uri, scheme] of validSchemes) {
- const parsed = fastURI.parse(uri)
- t.equal(parsed.error, undefined, uri)
- t.equal(parsed.scheme, scheme, uri + ' scheme')
- }
- for (const uri of malformedSchemes) {
- const parsed = fastURI.parse(uri)
- t.equal(parsed.error, MALFORMED_SCHEME_ERROR, uri)
- }
- t.end()
- })
- test('decoded schemes select their scheme handlers', (t) => {
- t.equal(
- fastURI.normalize('ht%74ps://example.com:443'),
- 'https://example.com/',
- 'HTTP normalization runs after decoding the scheme'
- )
- // 3.x has no mailto scheme handler (added in v4); use the ws handler to
- // verify that a percent-encoded scheme still selects its scheme handler
- const ws = fastURI.parse('we%62socket://example.com/')
- t.equal(ws.scheme, 'websocket', 'ws parsing runs after decoding the scheme')
- t.end()
- })
- test('normalize preserves schemes that decode to invalid identifiers', (t) => {
- for (const uri of malformedSchemes) {
- t.equal(fastURI.normalize(uri), uri, uri)
- }
- t.end()
- })
- test('scheme normalization cannot introduce authority or control delimiters', (t) => {
- const authority = '%2f%2fevil.example:/pwn'
- const crlf = '%0d%0aSet-Cookie:%20sid=attacker:/p'
- t.equal(fastURI.parse(authority).host, undefined, 'original input has no authority')
- t.equal(fastURI.normalize(authority), authority, 'normalization does not create an authority')
- t.equal(fastURI.normalize(crlf), crlf, 'normalization does not emit raw CRLF')
- t.equal(fastURI.normalize(crlf).includes('\r\n'), false, 'normalized output contains no raw CRLF')
- t.end()
- })
- test('equal returns false for malformed decoded schemes', (t) => {
- for (const uri of malformedSchemes) {
- t.equal(fastURI.equal(uri, uri, {}), false, uri)
- }
- t.end()
- })
- test('resolve rejects malformed decoded schemes in either input', (t) => {
- t.throws(
- () => fastURI.resolve('%2f%2fevil.example:/base', 'child'),
- /URI scheme is malformed\./,
- 'malformed base'
- )
- t.throws(
- () => fastURI.resolve('https://allowed.example/app/', '%2f%2fevil.example:/pwn'),
- /URI scheme is malformed\./,
- 'malformed relative reference'
- )
- t.end()
- })
- test('serialize validates decoded component schemes', (t) => {
- t.equal(
- fastURI.serialize({ scheme: 'foo%2Bbar', path: 'value' }),
- 'foo+bar:value',
- 'valid decoded scheme is serialized'
- )
- t.throws(
- () => fastURI.serialize({ scheme: '//evil.example', path: '/pwn' }),
- /URI scheme is malformed\./,
- 'raw invalid scheme'
- )
- t.throws(
- () => fastURI.serialize({ scheme: '%2f%2fevil.example', path: '/pwn' }),
- /URI scheme is malformed\./,
- 'encoded invalid scheme'
- )
- t.equal(
- fastURI.equal(
- { scheme: '%2f%2fevil.example', path: '/pwn' },
- { scheme: '%2f%2fevil.example', path: '/pwn' },
- {}
- ),
- false,
- 'equality fails closed for malformed component objects'
- )
- t.end()
- })
|