Skip to content

Commit 9997779

Browse files
authored
Merge branch 'develop' into dependabot/npm_and_yarn/marked-2.0.0
2 parents 242db94 + abda30d commit 9997779

File tree

8 files changed

+143
-42
lines changed

8 files changed

+143
-42
lines changed

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ Users and the development team are usually in the [Discord server](https://disco
3535

3636
_Vercel_ has given us a Pro account.
3737

38-
<a href="https://vercel.com/?utm_source=docsifyjsdocs" target="_blank"><img src="_media/vercel_logo.svg" width="100px"></a>
38+
<a href="https://vercel.com/?utm_source=docsifyjsdocs" target="_blank"><img src="https://cdn.jsdelivr.net/gh/docsifyjs/docsify/docs/_media/vercel_logo.svg" width="100px"></a>

docs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
}
197197
return (
198198
html +
199-
'<br/> <i>Vercel</i> has given us a Pro account <br/> <a href="https://vercel.com/?utm_source=docsifyjsdocs" target="_blank"><img src="_media/vercel_logo.svg" alt="Vercel" width="100" height="64"></a>'
199+
'<br/> <i>Vercel</i> has given us a Pro account <br/> <a href="https://vercel.com/?utm_source=docsifyjsdocs" target="_blank"><img src="https://cdn.jsdelivr.net/gh/docsifyjs/docsify/docs/_media/vercel_logo.svg" alt="Vercel" width="100" height="64"></a>'
200200
);
201201
});
202202
},

packages/docsify-server-renderer/package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/docsify-server-renderer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
},
1717
"dependencies": {
1818
"debug": "^4.3.2",
19-
"docsify": "^4.11.6",
19+
"docsify": "^4.12.0",
2020
"dompurify": "^2.2.6",
2121
"node-fetch": "^2.6.0",
2222
"resolve-pathname": "^3.0.0"

src/core/fetch/index.js

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable no-unused-vars */
22
import { callHook } from '../init/lifecycle';
33
import { getParentPath, stringifyQuery } from '../router/util';
4-
import { noop } from '../util/core';
4+
import { noop, isExternal } from '../util/core';
55
import { getAndActive } from '../event/sidebar';
66
import { get } from './ajax';
77

@@ -20,32 +20,6 @@ function loadNested(path, qs, file, next, vm, first) {
2020
).then(next, _ => loadNested(path, qs, file, next, vm));
2121
}
2222

23-
function isExternal(url) {
24-
let match = url.match(
25-
/^([^:/?#]+:)?(?:\/\/([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/
26-
);
27-
if (
28-
typeof match[1] === 'string' &&
29-
match[1].length > 0 &&
30-
match[1].toLowerCase() !== location.protocol
31-
) {
32-
return true;
33-
}
34-
if (
35-
typeof match[2] === 'string' &&
36-
match[2].length > 0 &&
37-
match[2].replace(
38-
new RegExp(
39-
':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$'
40-
),
41-
''
42-
) !== location.host
43-
) {
44-
return true;
45-
}
46-
return false;
47-
}
48-
4923
export function fetchMixin(proto) {
5024
let last;
5125

src/core/util/core.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,35 @@ export function noop() {}
6666
export function isFn(obj) {
6767
return typeof obj === 'function';
6868
}
69+
70+
/**
71+
* Check if url is external
72+
* @param {String} string url
73+
* @returns {Boolean} True if the passed-in url is external
74+
*/
75+
export function isExternal(url) {
76+
let match = url.match(
77+
/^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/
78+
);
79+
80+
if (
81+
typeof match[1] === 'string' &&
82+
match[1].length > 0 &&
83+
match[1].toLowerCase() !== location.protocol
84+
) {
85+
return true;
86+
}
87+
if (
88+
typeof match[2] === 'string' &&
89+
match[2].length > 0 &&
90+
match[2].replace(
91+
new RegExp(
92+
':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$'
93+
),
94+
''
95+
) !== location.host
96+
) {
97+
return true;
98+
}
99+
return false;
100+
}

test/e2e/security.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const docsifyInit = require('../helpers/docsify-init');
2+
3+
describe(`Security`, function() {
4+
const sharedOptions = {
5+
markdown: {
6+
homepage: '# Hello World',
7+
},
8+
routes: {
9+
'test.md': '# Test Page',
10+
},
11+
};
12+
13+
describe(`Cross Site Scripting (XSS)`, function() {
14+
const slashStrings = ['//', '///'];
15+
16+
for (const slashString of slashStrings) {
17+
const hash = `#${slashString}domain.com/file.md`;
18+
19+
test(`should not load remote content from hash (${hash})`, async () => {
20+
await docsifyInit(sharedOptions);
21+
await expect(page).toHaveText('#main', 'Hello World');
22+
await page.evaluate(() => (location.hash = '#/test'));
23+
await expect(page).toHaveText('#main', 'Test Page');
24+
await page.evaluate(newHash => {
25+
location.hash = newHash;
26+
}, hash);
27+
await expect(page).toHaveText('#main', 'Hello World');
28+
expect(page.url()).toMatch(/#\/$/);
29+
});
30+
}
31+
});
32+
});

test/unit/core-util.test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const { isExternal } = require('../../src/core/util');
2+
3+
// Core util
4+
// -----------------------------------------------------------------------------
5+
describe('core/util', () => {
6+
// isExternal()
7+
// ---------------------------------------------------------------------------
8+
describe('isExternal()', () => {
9+
// cases non external
10+
test('non external local url with one /', () => {
11+
const result = isExternal(`/${location.host}/docsify/demo.md`);
12+
13+
expect(result).toBeFalsy();
14+
});
15+
16+
test('non external local url with two //', () => {
17+
const result = isExternal(`//${location.host}/docsify/demo.md`);
18+
19+
expect(result).toBeFalsy();
20+
});
21+
22+
test('non external local url with three ///', () => {
23+
const result = isExternal(`///${location.host}/docsify/demo.md`);
24+
25+
expect(result).toBeFalsy();
26+
});
27+
28+
test('non external local url with more /', () => {
29+
const result = isExternal(
30+
`//////////////////${location.host}/docsify/demo.md`
31+
);
32+
33+
expect(result).toBeFalsy();
34+
});
35+
36+
test('non external url with one /', () => {
37+
const result = isExternal('/example.github.io/docsify/demo.md');
38+
39+
expect(result).toBeFalsy();
40+
});
41+
42+
// cases is external
43+
test('external url with two //', () => {
44+
const result = isExternal('/docsify/demo.md');
45+
46+
expect(result).toBeFalsy();
47+
});
48+
49+
test('external url with three ///', () => {
50+
const result = isExternal('///example.github.io/docsify/demo.md');
51+
52+
expect(result).toBeTruthy();
53+
});
54+
55+
test('external url with more /', () => {
56+
const result = isExternal(
57+
'//////////////////example.github.io/docsify/demo.md'
58+
);
59+
60+
expect(result).toBeTruthy();
61+
});
62+
});
63+
});

0 commit comments

Comments
 (0)