KeyWai — self-hosted приложение: вы разворачиваете его на своём сервере и сами отвечаете за сеть, TLS, секреты и обновления. Этот документ описывает модель угроз, встроенные защиты, известные риски и порядок сообщения об уязвимостях.
Проект развивается как единый монолит. Исправления безопасности выходят в
последней версии (ветка main и последний релиз). Отдельные старые версии не
сопровождаются — обновляйтесь до актуальной (см. docs/operations.md).
KeyWai рассчитан на доверенное окружение одной команды, а не на публичный мультитенант. В зоне ответственности оператора (того, кто развернул):
- хост и сеть (firewall, закрытые порты БД/Redis — в проде они не публикуются);
- TLS-терминация (внешний reverse-proxy или nginx, см. docs/operations.md);
- хранение секретов (
backend/.env,./data/keys/keys.env); - регулярные обновления и резервные копии.
При запуске с config.settings.production (профиль docker-compose.prod.yml):
- HTTPS-редирект и secure-cookies — включаются переключателем
HTTPS_ENABLED(по умолчаниюtrue); за TLS-прокси редирект становится no-op черезSECURE_PROXY_SSL_HEADER. - HSTS —
max-age1 год, с поддоменами и preload. - Content Security Policy —
default-src 'self',script-src 'self'(безunsafe-inlineдля скриптов),frame-ancestors 'none',upgrade-insecure-requests. - Прочие заголовки —
X-Frame-Options: DENY,X-Content-Type-Options: nosniff, XSS-filter. - CORS — по умолчанию пуст: фронтенд и API отдаются с одного origin за reverse-proxy, межсайтовых запросов нет.
- Шифрование секретов — все ключи в
SystemConfig(введённые через админку) шифруются Fernet; ключ шифрования — в./data/keys/keys.env. - Санитизация ввода — HTML из rich-text-редактора чистится DOMPurify;
внешние запросы (анализ конкурентов) проходят через SSRF-защиту
(
apps/core/ssrf.py). - Скан секретов —
.gitleaks.toml+detect-secretsв pre-commit;.env,./dataи ключи — в.gitignore/.dockerignore.
Токены доступа и обновления хранятся в localStorage (или sessionStorage при
выключенном «Запомнить меня»), ключ keywai-auth. Они читаемы из JavaScript —
при XSS-уязвимости их можно похитить.
Что смягчает риск в проекте: строгий CSP (script-src 'self') в проде,
санитизация пользовательского HTML (DOMPurify), короткое время жизни
access-токена (60 минут) с ротацией refresh-токена.
Оператору: обязательно поднимайте прод под HTTPS (без этого secure-cookies и часть защит отключены), не встраивайте сторонний неаудированный JS, не отключайте CSP.
GET /api/v1/parsing/health/ в режиме DEBUG открыт, а в проде требует заголовок
X-Health-Token (значение из env HEALTH_CHECK_TOKEN) или запрос с разрешённого
IP (HEALTH_CHECK_ALLOWED_IPS, по умолчанию 127.0.0.1).
Рекомендация: на проде задайте HEALTH_CHECK_TOKEN в backend/.env (переменной
нет в .env.example — добавьте вручную) и/или ограничьте доступ к эндпоинту на
уровне reverse-proxy.
FERNET_KEY (в ./data/keys/keys.env, генерируется автоматически при первом
запуске) расшифровывает все секреты из SystemConfig.
- Потеря ключа → сохранённые в админке ключи становятся нечитаемыми, их придётся вводить заново.
- Утечка ключа вместе с дампом БД → злоумышленник расшифрует все секреты.
Храните keys.env отдельно от дампа БД, с правами chmod 600, и обязательно
включайте в резервную копию (scripts/backup.sh это делает — см.
docs/operations.md).
Никогда не коммитьте keys.env и backend/.env.
SECRET_KEYDjango генерируется автоматически вkeys.env— не публикуйте его.- Не запускайте прод на dev-настройках: профиль
production.pyфорсируетDEBUG=Falseи весь набор защит выше.
Не публикуйте уязвимости в публичных issue или pull request.
Сообщите приватно одним из способов:
- GitHub Security Advisories — вкладка Security → Report a vulnerability репозитория (приватный канал, если включён);
- Telegram — @andrejtsibin.
По возможности приложите: описание проблемы, шаги воспроизведения, затронутую версию/коммит и потенциальное влияние. Это сольный проект — ответ по мере возможности, без жёстких SLA. Спасибо за ответственное раскрытие.
SUPPORT_EMAILв админке — это адрес поддержки вашей инсталляции для её пользователей, а не канал раскрытия уязвимостей апстрим-проекту.