Add path validation for chat directory operations
This commit is contained in:
+24
-3
@@ -20,6 +20,7 @@ import {
|
||||
tryReadFileSync,
|
||||
tryDeleteFile,
|
||||
readFirstLine,
|
||||
isPathUnderParent,
|
||||
} from '../util.js';
|
||||
|
||||
const isBackupEnabled = !!getConfigValue('backups.chat.enabled', true, 'boolean');
|
||||
@@ -473,6 +474,9 @@ router.post('/save', validateAvatarUrlMiddleware, async function (request, respo
|
||||
const chatData = request.body.chat;
|
||||
const chatFileName = `${String(request.body.file_name)}.jsonl`;
|
||||
const chatFilePath = path.join(request.user.directories.chats, cardName, sanitize(chatFileName));
|
||||
if (!isPathUnderParent(request.user.directories.chats, chatFilePath)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
|
||||
if (Array.isArray(chatData)) {
|
||||
await trySaveChat(chatData, chatFilePath, request.body.force, handle, cardName, request.user.directories.backups);
|
||||
@@ -514,6 +518,9 @@ router.post('/get', validateAvatarUrlMiddleware, function (request, response) {
|
||||
try {
|
||||
const dirName = String(request.body.avatar_url).replace('.png', '');
|
||||
const directoryPath = path.join(request.user.directories.chats, dirName);
|
||||
if (!isPathUnderParent(request.user.directories.chats, directoryPath)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
const chatDirExists = fs.existsSync(directoryPath);
|
||||
|
||||
//if no chat dir for the character is found, make one with the character name
|
||||
@@ -545,6 +552,9 @@ router.post('/rename', validateAvatarUrlMiddleware, async function (request, res
|
||||
const pathToFolder = request.body.is_group
|
||||
? request.user.directories.groupChats
|
||||
: path.join(request.user.directories.chats, String(request.body.avatar_url).replace('.png', ''));
|
||||
if (!request.body.is_group && !isPathUnderParent(request.user.directories.chats, pathToFolder)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
const pathToOriginalFile = path.join(pathToFolder, sanitize(request.body.original_file));
|
||||
const pathToRenamedFile = path.join(pathToFolder, sanitize(request.body.renamed_file));
|
||||
const sanitizedFileName = path.parse(pathToRenamedFile).name;
|
||||
@@ -575,6 +585,9 @@ router.post('/delete', validateAvatarUrlMiddleware, function (request, response)
|
||||
const dirName = String(request.body.avatar_url).replace('.png', '');
|
||||
const chatFileName = String(request.body.chatfile);
|
||||
const chatFilePath = path.join(request.user.directories.chats, dirName, sanitize(chatFileName));
|
||||
if (!isPathUnderParent(request.user.directories.chats, chatFilePath)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
//Return success if the file was deleted.
|
||||
if (tryDeleteFile(chatFilePath)) {
|
||||
return response.send({ ok: true });
|
||||
@@ -595,7 +608,10 @@ router.post('/export', validateAvatarUrlMiddleware, async function (request, res
|
||||
const pathToFolder = request.body.is_group
|
||||
? request.user.directories.groupChats
|
||||
: path.join(request.user.directories.chats, String(request.body.avatar_url).replace('.png', ''));
|
||||
let filename = path.join(pathToFolder, sanitize(request.body.file));
|
||||
const filename = path.join(pathToFolder, sanitize(request.body.file));
|
||||
if (!request.body.is_group && !isPathUnderParent(request.user.directories.chats, filename)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
let exportfilename = request.body.exportfilename;
|
||||
if (!fs.existsSync(filename)) {
|
||||
const errorMessage = {
|
||||
@@ -690,6 +706,11 @@ router.post('/import', validateAvatarUrlMiddleware, function (request, response)
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
|
||||
const directoryPath = path.join(request.user.directories.chats, avatarUrl);
|
||||
if (!isPathUnderParent(request.user.directories.chats, directoryPath)) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
|
||||
try {
|
||||
const pathToUpload = path.join(request.file.destination, request.file.filename);
|
||||
const data = fs.readFileSync(pathToUpload, 'utf8');
|
||||
@@ -718,7 +739,7 @@ router.post('/import', validateAvatarUrlMiddleware, function (request, response)
|
||||
|
||||
const handleChat = (chat) => {
|
||||
const fileName = `${characterName} - ${humanizedDateTime()} imported.jsonl`;
|
||||
const filePath = path.join(request.user.directories.chats, avatarUrl, fileName);
|
||||
const filePath = path.join(directoryPath, fileName);
|
||||
fileNames.push(fileName);
|
||||
writeFileAtomicSync(filePath, chat, 'utf8');
|
||||
};
|
||||
@@ -757,7 +778,7 @@ router.post('/import', validateAvatarUrlMiddleware, function (request, response)
|
||||
}
|
||||
|
||||
const fileName = `${characterName} - ${humanizedDateTime()} imported.jsonl`;
|
||||
const filePath = path.join(request.user.directories.chats, avatarUrl, fileName);
|
||||
const filePath = path.join(directoryPath, fileName);
|
||||
fileNames.push(fileName);
|
||||
if (flattenedChat !== data) {
|
||||
writeFileAtomicSync(filePath, flattenedChat, 'utf8');
|
||||
|
||||
Reference in New Issue
Block a user