From 68c1e72efa0ea426a6f13369d23a8d119cc62023 Mon Sep 17 00:00:00 2001 From: Mimi <1119186082@qq.com> Date: Wed, 26 Jul 2023 16:59:33 +0800 Subject: [PATCH 1/5] fix(tag/include_code): prevent path traversal --- lib/plugins/tag/include_code.ts | 40 +++++++++++++++---------------- test/scripts/tags/include_code.ts | 6 ++++- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts index 78edbe1bdb..423eae80d3 100644 --- a/lib/plugins/tag/include_code.ts +++ b/lib/plugins/tag/include_code.ts @@ -47,32 +47,32 @@ 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 src = join(codeDir, path); // 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: string) => { - if (!code) return; + // Prevent path traversal: https://github.com/hexojs/hexo/issues/5250 + const Page = ctx.model('Page'); + const doc = Page.findOne({ source: src }); + 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 (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}
`;
- });
+ return `${code}
`;
};
diff --git a/test/scripts/tags/include_code.ts b/test/scripts/tags/include_code.ts
index fa23a993f1..e2c558aa93 100644
--- a/test/scripts/tags/include_code.ts
+++ b/test/scripts/tags/include_code.ts
@@ -23,7 +23,11 @@ describe('include_code', () => {
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));
From e74644f131703979f0803a5312f2c7cd475dfccd Mon Sep 17 00:00:00 2001
From: Mimi <1119186082@qq.com>
Date: Thu, 27 Jul 2023 09:49:12 +0800
Subject: [PATCH 2/5] remove import
---
lib/plugins/tag/include_code.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts
index 423eae80d3..2acd3d2546 100644
--- a/lib/plugins/tag/include_code.ts
+++ b/lib/plugins/tag/include_code.ts
@@ -1,4 +1,3 @@
-import { exists, readFile } from 'hexo-fs';
import { basename, extname, join, posix } from 'path';
import type Hexo from '../../hexo';
From 48d3cbcefaff2c5ec39d6fc00dcf7cd576c89ded Mon Sep 17 00:00:00 2001
From: uiolee <22849383+uiolee@users.noreply.github.com>
Date: Tue, 12 Sep 2023 21:18:54 +0800
Subject: [PATCH 3/5] fix: windos escapeBackslash
---
lib/plugins/tag/include_code.ts | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts
index 2acd3d2546..b2f09e972b 100644
--- a/lib/plugins/tag/include_code.ts
+++ b/lib/plugins/tag/include_code.ts
@@ -13,6 +13,11 @@ const rTo = /\s*to:(\d+)/i;
* {% include_code [title] [lang:language] path/to/file %}
*/
+const escapeBackslash = path => {
+ // Replace backslashes on Windows
+ return path.replace(/\\/g, '/');
+};
+
export = (ctx: Hexo) => function includeCodeTag(args: string[]) {
let codeDir = ctx.config.code_dir;
let arg = args.join(' ');
@@ -46,7 +51,7 @@ 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(codeDir, path);
+ const src = escapeBackslash(join(codeDir, path));
// If the title is not defined, use file name instead
const title = match[1] || basename(path);
@@ -72,6 +77,5 @@ export = (ctx: Hexo) => function includeCodeTag(args: string[]) {
args: [code, options]
});
}
-
return `${code}
`;
};
From 04abf7168fa9567b935785be96b44d50e65b82ec Mon Sep 17 00:00:00 2001
From: Mimi <1119186082@qq.com>
Date: Tue, 9 Apr 2024 16:02:53 +0800
Subject: [PATCH 4/5] fix: no backslash
---
lib/plugins/tag/include_code.ts | 20 ++++++++------------
test/scripts/tags/include_code.ts | 2 +-
2 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts
index b2f09e972b..fb6322f5e9 100644
--- a/lib/plugins/tag/include_code.ts
+++ b/lib/plugins/tag/include_code.ts
@@ -1,4 +1,5 @@
-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+)/;
@@ -13,11 +14,6 @@ const rTo = /\s*to:(\d+)/i;
* {% include_code [title] [lang:language] path/to/file %}
*/
-const escapeBackslash = path => {
- // Replace backslashes on Windows
- return path.replace(/\\/g, '/');
-};
-
export = (ctx: Hexo) => function includeCodeTag(args: string[]) {
let codeDir = ctx.config.code_dir;
let arg = args.join(' ');
@@ -51,21 +47,21 @@ 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 = escapeBackslash(join(codeDir, path));
-
- // If the title is not defined, use file name instead
- const title = match[1] || basename(path);
- const caption = `${title}view raw`;
+ const source = join(codeDir, path);
// Prevent path traversal: https://github.com/hexojs/hexo/issues/5250
const Page = ctx.model('Page');
- const doc = Page.findOne({ source: src });
+ const doc = Page.findOne({ source });
if (!doc) return;
let code = doc.content;
const lines = code.split('\n');
code = lines.slice(from, to).join('\n').trim();
+ // If the title is not defined, use file name instead
+ const title = match[1] || basename(path);
+ const caption = `${title}view raw`;
+
if (ctx.extend.highlight.query(ctx.config.syntax_highlighter)) {
const options = {
lang,
diff --git a/test/scripts/tags/include_code.ts b/test/scripts/tags/include_code.ts
index e2c558aa93..7d104fbf80 100644
--- a/test/scripts/tags/include_code.ts
+++ b/test/scripts/tags/include_code.ts
@@ -16,7 +16,7 @@ describe('include_code', () => {
const defaultCfg = JSON.parse(JSON.stringify(hexo.config));
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();',
'}'
].join('\n');
From a640450fe0c2d32ae43fa7089868798e5d9fb981 Mon Sep 17 00:00:00 2001
From: Mimi <1119186082@qq.com>
Date: Tue, 9 Apr 2024 20:46:58 +0800
Subject: [PATCH 5/5] fix unit test
---
lib/plugins/tag/include_code.ts | 2 +-
test/scripts/tags/include_code.ts | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts
index fb6322f5e9..cc059bb1f2 100644
--- a/lib/plugins/tag/include_code.ts
+++ b/lib/plugins/tag/include_code.ts
@@ -47,7 +47,7 @@ export = (ctx: Hexo) => function includeCodeTag(args: string[]) {
// If the language is not defined, use file extension instead
lang = lang || extname(path).substring(1);
- const source = join(codeDir, path);
+ const source = join(codeDir, path).replace(/\\/g, '/');
// Prevent path traversal: https://github.com/hexojs/hexo/issues/5250
const Page = ctx.model('Page');
diff --git a/test/scripts/tags/include_code.ts b/test/scripts/tags/include_code.ts
index 7d104fbf80..bbbb37e7fd 100644
--- a/test/scripts/tags/include_code.ts
+++ b/test/scripts/tags/include_code.ts
@@ -99,7 +99,7 @@ describe('include_code', () => {
it('to', async () => {
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();'
].join('\n');
const expected = highlight(fixture, {
@@ -177,7 +177,7 @@ describe('include_code', () => {
it('to', async () => {
const fixture = [
- 'if (tired && night){',
+ 'if (tired && night) {',
' sleep();'
].join('\n');
const expected = prismHighlight(fixture, {