diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts index c3d56d2fca..cc059bb1f2 100644 --- a/lib/plugins/tag/include_code.ts +++ b/lib/plugins/tag/include_code.ts @@ -1,5 +1,5 @@ -import { exists, readFile } from 'hexo-fs'; -import { basename, extname, join, posix } from 'path'; +import { basename, extname, join } from 'path'; +import { url_for } from 'hexo-util'; import type Hexo from '../../hexo'; const rCaptionTitleFile = /(.*)?(?:\s+|^)(\/*\S+)/; @@ -47,32 +47,31 @@ export = (ctx: Hexo) => function includeCodeTag(args: string[]) { // If the language is not defined, use file extension instead lang = lang || extname(path).substring(1); - const src = join(ctx.source_dir, codeDir, path); + const source = join(codeDir, path).replace(/\\/g, '/'); - // If the title is not defined, use file name instead - const title = match[1] || basename(path); - const caption = `${title}view raw`; - - return exists(src).then(exist => { - if (exist) return readFile(src); - }).then(code => { - if (!code) return; + // Prevent path traversal: https://github.com/hexojs/hexo/issues/5250 + const Page = ctx.model('Page'); + const doc = Page.findOne({ source }); + if (!doc) return; - const lines = code.split('\n'); - code = lines.slice(from, to).join('\n').trim(); + let code = doc.content; + const lines = code.split('\n'); + code = lines.slice(from, to).join('\n').trim(); - if (ctx.extend.highlight.query(ctx.config.syntax_highlighter)) { - const options = { - lang, - caption, - lines_length: lines.length - }; - return ctx.extend.highlight.exec(ctx.config.syntax_highlighter, { - context: ctx, - args: [code, options] - }); - } + // If the title is not defined, use file name instead + const title = match[1] || basename(path); + const caption = `${title}view raw`; - return `
${code}
`;
- });
+ if (ctx.extend.highlight.query(ctx.config.syntax_highlighter)) {
+ const options = {
+ lang,
+ caption,
+ lines_length: lines.length
+ };
+ return ctx.extend.highlight.exec(ctx.config.syntax_highlighter, {
+ context: ctx,
+ args: [code, options]
+ });
+ }
+ return `${code}
`;
};
diff --git a/test/scripts/tags/include_code.ts b/test/scripts/tags/include_code.ts
index fa23a993f1..bbbb37e7fd 100644
--- a/test/scripts/tags/include_code.ts
+++ b/test/scripts/tags/include_code.ts
@@ -16,14 +16,18 @@ describe('include_code', () => {
const defaultCfg = JSON.parse(JSON.stringify(hexo.config));
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();',
'}'
].join('\n');
const code = args => includeCode(args.split(' '));
- before(() => writeFile(path, fixture));
+ before(async () => {
+ await writeFile(path, fixture);
+ await hexo.init();
+ await hexo.load();
+ });
beforeEach(() => {
hexo.config = JSON.parse(JSON.stringify(defaultCfg));
@@ -95,7 +99,7 @@ describe('include_code', () => {
it('to', async () => {
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();'
].join('\n');
const expected = highlight(fixture, {
@@ -173,7 +177,7 @@ describe('include_code', () => {
it('to', async () => {
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();'
].join('\n');
const expected = prismHighlight(fixture, {