From 3fdd9cf12f975043742996d5b76e09e068827201 Mon Sep 17 00:00:00 2001 From: "s.zotov" Date: Sun, 12 Apr 2026 20:46:43 +0000 Subject: [PATCH] Add "Security" --- Security.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 Security.md diff --git a/Security.md b/Security.md new file mode 100644 index 0000000..adca958 --- /dev/null +++ b/Security.md @@ -0,0 +1,125 @@ +# Пользователи и безопасность + +## Управление пользователями + +### Создание (admin only) +- Логин: уникальный, непустой +- Пароль: минимум 8 символов +- Роль: `admin` или `user` +- Проекты: массив доступных проектов (сейчас всегда `['vipavenue']`) + +### Роли +| Возможность | admin | user | +|-------------|-------|------| +| Сборка писем | ✅ | ✅ | +| Рендер превью | ✅ | ✅ | +| FTP загрузка | ✅ | ✅ | +| Spell/Link check | ✅ | ✅ | +| Изменение settings | ✅ | ❌ | +| Изменение config (Yonote, URLs) | ✅ | ❌ | +| Управление пользователями | ✅ | ❌ | + +### Пользовательские настройки +Сохраняются в профиле на сервере (PUT `/api/auth/preferences`): +- `theme` — 'light' / 'dark' +- `activePage` — последняя активная страница +- `previewZoom` — масштаб превью (40-100) + +## Аудит безопасности (апрель 2026) + +### 1. Pug Template Injection (CRITICAL → FIXED) + +**Проблема:** Пользовательский текст `#{process.cwd()}` в поле блока попадал в `let.pug` и выполнялся на сервере при Pug-компиляции. Потенциально: `#{require('child_process').execSync('rm -rf /')}`. + +**Фикс:** Экранирование `#{` и `!{` в пользовательском pug перед записью в файл: +```javascript +const pug = String(body.pug || '').replace(/([#!])\{/g, '$1\\{') +``` +Не ломает миксины — `+spacerLine(40)` не использует интерполяцию. + +Preheader дополнительно очищается от `\r\n\`\\` для предотвращения выхода из строки `+preheader("...")`. + +### 2. XSS через iframe превью (HIGH → FIXED) + +**Проблема:** `` в HTML письма выполнялся в iframe без sandbox. Алерт выполнялся в контексте aspekter.ru — доступ к cookies, DOM основной страницы. + +**Фикс:** +- `sandbox="allow-same-origin"` на iframe — скрипты заблокированы, DOM доступен +- Click detection переписан: вместо инъекции `