docs: move the accepted security risks into docs/security.md
The plan holds undone work; an accepted risk is a decision, not a task — it has no place in a queue, only a condition for revisiting it. Both risks (POST with neither Sec-Fetch-Site nor Origin, no session-bound CSRF tokens) move verbatim into a new docs/security.md, which also states where D.5 findings land. Section letters and item numbering in the plan stay as they were, since progress.md and the commit history reference them; a note in their place points at the new file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# Безопасность: принятые риски
|
||||
|
||||
**Что здесь.** Обязательные требования к безопасности — [ТЗ 7.6](specification.md);
|
||||
соответствие им проверено полным аудитом на v1.0 и здесь не пересказывается.
|
||||
Hardening сверх обязательного 7.6 (security-заголовки, проверка origin, cookie
|
||||
`__Host-` с обнаружением дублей — Фаза 14) тоже закрыт, история — в
|
||||
[CHANGELOG.md](../CHANGELOG.md) и `git log`. Этот документ держит третью
|
||||
категорию: то, что закрыто **сознательно не было**, чтобы решение не потерялось
|
||||
и не переоткрывалось заново.
|
||||
|
||||
Здесь, а не в [implementation-plan.md](implementation-plan.md), потому что план —
|
||||
только про несделанную работу, а принятый риск — не работа, а решение: у него нет
|
||||
состояния «в очереди», есть условие, при котором к нему возвращаются.
|
||||
|
||||
## Принятые риски
|
||||
|
||||
- **`POST` без `Sec-Fetch-Site` и без `Origin` пропускается.**
|
||||
Клиент, не посылающий ни одного из двух — по-настоящему старый браузер или
|
||||
webview с замороженным движком, — остаётся уязвим к CSRF с любого сайта.
|
||||
Принято сознательно: панель однопользовательская, админ выбирает браузер
|
||||
сам, а строгий режим не «защитил бы» такой клиент, а просто сломал бы в нём
|
||||
панель. Ужесточение — одна строка в `originAllowed`
|
||||
([internal/web/security.go](../internal/web/security.go)): вернуть `false`
|
||||
вместо `true` в ветке «нет обоих заголовков».
|
||||
- **CSRF-токены, привязанные к сессии, не делаются.** Проверка origin
|
||||
закрывает соседний поддомен, но зависит от поведения браузера; токен — нет.
|
||||
Цена — скрытое поле примерно в двух десятках форм. Триггером вернуться к
|
||||
вопросу считать появление требования «устойчиво независимо от браузера».
|
||||
От XSS внутри самой панели не спас бы и токен: код, исполняющийся в origin
|
||||
панели, отправит запрос сам — против этого работают автоэкранирование
|
||||
`html/template` (7.6.7) и CSP, поэтому шаблоны не должны содержать
|
||||
inline-скриптов и inline-стилей.
|
||||
|
||||
## Как этот список пополняется
|
||||
|
||||
Предрелизная проверка на уязвимости (пункт **D.5** плана, модель Fable) закрывает
|
||||
каждую находку одним из двух способов: правка до тега — либо запись сюда, с
|
||||
обоснованием и условием возврата, как у двух пунктов выше. Третьего варианта
|
||||
(«посмотрели и ладно») нет.
|
||||
Reference in New Issue
Block a user