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 переписан: вместо инъекции `