修复配置文件路径可能越权

This commit is contained in:
whyour
2026-06-12 23:45:40 +08:00
parent 6796068523
commit d1dfde3ca9
2 changed files with 32 additions and 23 deletions
+14 -11
View File
@@ -4,7 +4,7 @@ import { Logger } from 'winston';
import config from '../config';
import * as fs from 'fs/promises';
import { celebrate, Joi } from 'celebrate';
import { join } from 'path';
import { join, basename } from 'path';
import { SAMPLE_FILES } from '../config/const';
import { t } from '../shared/i18n';
import ConfigService from '../services/config';
@@ -72,20 +72,23 @@ export default (app: Router) => {
const logger: Logger = Container.get('logger');
try {
const { name, content } = req.body;
if (config.blackFileList.includes(name)) {
res.send({ code: 403, message: t('文件无法访问') });
}
let path = join(config.configPath, name);
// Resolve path first to prevent traversal attacks
let basePath = config.configPath;
if (name.startsWith('data/scripts/')) {
path = join(config.rootPath, name);
basePath = join(config.rootPath, 'data/scripts');
}
if (
!path.startsWith(config.configPath) &&
!path.startsWith(config.scriptPath)
) {
const cleanName = name.replace(/^data\/scripts\//, '');
const resolvedPath = join(basePath, cleanName);
const normalized = join(resolvedPath);
// Verify the resolved path stays within allowed directory
if (!normalized.startsWith(basePath)) {
return res.send({ code: 403, message: t('文件路径无效') });
}
await writeFileWithLock(path, content);
// Check blacklist on actual filename (not user input)
if (config.blackFileList.includes(basename(normalized))) {
return res.send({ code: 403, message: t('文件无法访问') });
}
await writeFileWithLock(normalized, content);
res.send({ code: 200, message: t('保存成功') });
} catch (e) {
return next(e);