fix(security): харднинг загрузки файлов, контроль доступа и XSS
Подхвачено из закрытой параллельной сессии (план project_hardening_2026). Загрузки: magic.js получает safeExt/EXT_FOR_MIME — имя файла на диске берёт расширение из проверенного MIME, а не из client originalname (анти stored-XSS .html/.svg). avatar/flashcard/chat-загрузки дополнительно проверяют magic-байты: содержимое должно соответствовать MIME, иначе файл удаляется и 400. Доступ: fileController.getFolderAccess отдаёт список раздачи только владельцу или админу (была утечка имён/email учеников). testController.getOne гейтит видимость как list() — ученик не прочитает тексты заданий черновиков/вариантов по id. XSS: classes.html escJ() экранирует строку для JS-литерала в inline-onclick (имя ученика с кавычкой больше не ломает обработчик). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,20 @@ const MAGIC = [
|
||||
{ mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', bytes: [0x50,0x4B,0x03,0x04], offset: 0 },
|
||||
];
|
||||
|
||||
/* Канонические расширения по проверенному MIME. Имя файла на диске берём
|
||||
* ОТСЮДА, а не из client-controlled originalname, иначе можно сохранить
|
||||
* .html/.svg и получить stored-XSS при раздаче статикой. */
|
||||
const EXT_FOR_MIME = {
|
||||
'image/png': '.png',
|
||||
'image/jpeg': '.jpg',
|
||||
'image/gif': '.gif',
|
||||
'image/webp': '.webp',
|
||||
'application/pdf': '.pdf',
|
||||
};
|
||||
function safeExt(declaredMime, fallback) {
|
||||
return EXT_FOR_MIME[declaredMime] || fallback || '';
|
||||
}
|
||||
|
||||
function checkMagicBytes(filePath, declaredMime) {
|
||||
if (declaredMime === 'text/plain') return true; // txt has no magic bytes
|
||||
const rules = MAGIC.filter(m => m.mime === declaredMime);
|
||||
@@ -35,4 +49,4 @@ function checkMagicBytes(filePath, declaredMime) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { checkMagicBytes };
|
||||
module.exports = { checkMagicBytes, safeExt, EXT_FOR_MIME };
|
||||
|
||||
Reference in New Issue
Block a user