From 702beb9d8766c165d155c8bb53786360158a421d Mon Sep 17 00:00:00 2001 From: koooooo-7 <369491420@qq.com> Date: Thu, 18 Feb 2021 20:01:46 +0800 Subject: [PATCH 1/2] test(unit): add test cases on xss. --- src/core/fetch/index.js | 28 +---------------- src/core/util/core.js | 32 +++++++++++++++++++ test/unit/core-util.test.js | 63 +++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 test/unit/core-util.test.js diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index 2d6f813c2..f0f288798 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -1,7 +1,7 @@ /* eslint-disable no-unused-vars */ import { callHook } from '../init/lifecycle'; import { getParentPath, stringifyQuery } from '../router/util'; -import { noop } from '../util/core'; +import { noop, isExternal } from '../util/core'; import { getAndActive } from '../event/sidebar'; import { get } from './ajax'; @@ -20,32 +20,6 @@ function loadNested(path, qs, file, next, vm, first) { ).then(next, _ => loadNested(path, qs, file, next, vm)); } -function isExternal(url) { - let match = url.match( - /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ - ); - if ( - typeof match[1] === 'string' && - match[1].length > 0 && - match[1].toLowerCase() !== location.protocol - ) { - return true; - } - if ( - typeof match[2] === 'string' && - match[2].length > 0 && - match[2].replace( - new RegExp( - ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$' - ), - '' - ) !== location.host - ) { - return true; - } - return false; -} - export function fetchMixin(proto) { let last; diff --git a/src/core/util/core.js b/src/core/util/core.js index 9d2638412..50b7ed02c 100644 --- a/src/core/util/core.js +++ b/src/core/util/core.js @@ -66,3 +66,35 @@ export function noop() {} export function isFn(obj) { return typeof obj === 'function'; } + +/** + * Check if url is external + * @param {String} string url + * @returns {Boolean} True if the passed-in url is external + */ +export function isExternal(url) { + let match = url.match( + /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ + ); + + if ( + typeof match[1] === 'string' && + match[1].length > 0 && + match[1].toLowerCase() !== location.protocol + ) { + return true; + } + if ( + typeof match[2] === 'string' && + match[2].length > 0 && + match[2].replace( + new RegExp( + ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$' + ), + '' + ) !== location.host + ) { + return true; + } + return false; +} diff --git a/test/unit/core-util.test.js b/test/unit/core-util.test.js new file mode 100644 index 000000000..68cf980bb --- /dev/null +++ b/test/unit/core-util.test.js @@ -0,0 +1,63 @@ +const { isExternal } = require('../../src/core/util'); + +// Core util +// ----------------------------------------------------------------------------- +describe('core/util', () => { + // isExternal() + // --------------------------------------------------------------------------- + describe('isExternal()', () => { + // cases non external + test('non external local url with one /', () => { + const result = isExternal(`/${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with two //', () => { + const result = isExternal(`//${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with three ///', () => { + const result = isExternal(`//${location.host}/docsify/demo.md`); + + expect(result).toBeFalsy(); + }); + + test('non external local url with more /', () => { + const result = isExternal( + `//////////////////${location.host}/docsify/demo.md` + ); + + expect(result).toBeFalsy(); + }); + + test('non external url with one /', () => { + const result = isExternal('/example.github.io/docsify/demo.md'); + + expect(result).toBeFalsy(); + }); + + // cases is external + test('external url with two //', () => { + const result = isExternal('/docsify/demo.md'); + + expect(result).toBeFalsy(); + }); + + test('external url with three ///', () => { + const result = isExternal('///example.github.io/docsify/demo.md'); + + expect(result).toBeTruthy(); + }); + + test('external url with more /', () => { + const result = isExternal( + '//////////////////example.github.io/docsify/demo.md' + ); + + expect(result).toBeTruthy(); + }); + }); +}); From eaf3fbc14a76871fa9497a1f210534d039719167 Mon Sep 17 00:00:00 2001 From: koooooo-7 <369491420@qq.com> Date: Thu, 18 Feb 2021 21:13:53 +0800 Subject: [PATCH 2/2] code refine. --- test/unit/core-util.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/core-util.test.js b/test/unit/core-util.test.js index 68cf980bb..0ebbf7bbd 100644 --- a/test/unit/core-util.test.js +++ b/test/unit/core-util.test.js @@ -20,7 +20,7 @@ describe('core/util', () => { }); test('non external local url with three ///', () => { - const result = isExternal(`//${location.host}/docsify/demo.md`); + const result = isExternal(`///${location.host}/docsify/demo.md`); expect(result).toBeFalsy(); });