В обсуждении безопасности легко получить два несвязанных списка: слева угрозы, справа controls. Между ними нет правила, поэтому review принимает любое знакомое слово. Проблема проявляется при изменении: control остаётся в коде, но никто не знает, какая отрицательная ветка должна доказать его работу. Цена — ложное закрытие риска и трудный откат: нельзя понять, какую гарантию потеряем, если удалить изменение.
Разберём связь на одной учебной модели. Актив change-request приходит от browser-client и пересекает public-api-to-handler. Злоупотребление — передать запрос без valid signature. Control signed-request обещает ровно одно: handler не принимает вход без проверяемой подписи. Evidence — результат локальной проверки отказа для специально заданного неподписанного значения. Модель не реализует подпись и не говорит, что у продукта есть такой endpoint. Она показывает, как записать связь до реализации.
DFD здесь нужен как граница предположений
Data flow diagram часто пытаются превратить в архитектурную картину на все случаи. Для малого review достаточно четырёх сущностей: source, flow, process и store. На стрелке между source и process лежит trust boundary: после неё нельзя считать вход уже доверенным. Store не обязан быть базой данных; в учебной записи это только место, где оказался asset. Такое упрощение полезно, пока оно честно: мы не показываем протокол, изоляцию сети, репликацию или журнал.
У угрозы тоже должен быть глагол. «Подделка» слишком широка, пока не сказано, что делает актор и какое свойство актива нарушает. Формулировка «send request without a valid signature» даёт отрицательный пример. Проверка может установить входное условие без подписи и ожидать отказ по договору handler. Она не доказывает отсутствие всех способов подделки, не проводит криптоанализ и не заменяет тест границ инфраструктуры.
| Слой | Запись в учебной модели | Вопрос ревьюера | Недопустимый вывод |
|---|---|---|---|
| Asset | change-request | что потеряет смысл при нарушении? | что защищены все данные продукта |
| Threat | unsigned request | какое действие пытаемся остановить? | что перечислены все злоупотребления |
| Control | signed-request | какую точку решения меняем? | что выбранный механизм достаточен |
| Evidence | local rejection check | какой наблюдаемый отказ ждём? | что выполнен security test среды |
| Rollback | restore snapshot | что вернётся в учебной записи? | что production rollout безопасно отменён |
Почему один control должен иметь названный evidence
Контроль иногда действительно требует нескольких проверок, но начинать полезно с минимальной пары. Если для signed-request нельзя назвать хотя бы одну отрицательную ветку, команда ещё не понимает его контракт. Если evidence — только «код прочитан», оно может быть разумным для дизайна, но не должно называться доказательством поведения. Хорошая запись разделяет эти виды: design review проверяет выбор границы, unit test проверяет локальный reject, а внешний security assessment имеет другой объект и критерий.
NIST SP 800-53 Rev. 5 — каталог controls, а не генератор тестов. Его роль в этой статье ограничена словарём: security control имеет функцию и нуждается в уверенности, что функция работает. Из этого не следует, что любой control стоит тащить в маленький сервис или что имя control заменяет спецификацию. Для выбранного потока достаточно сделать связь видимой, затем спросить владельца домена, нужна ли она вообще.
Исполнимый контракт и его отрицательные ветки
Функция planTeachingThreatModel принимает только заранее названные строки. Пустой asset, отсутствующая boundary и неизвестный control отклоняются. Это намеренная строгость учебной модели: ей запрещено достраивать пропущенный контекст. Объект результата содержит dfd, threat, control и evidence, а также snapshot для rollback. Никаких скрытых глобальных данных нет, поэтому fixture повторяем на любой машине с Node.
const plan = planTeachingThreatModel({
actor: 'browser-client',
asset: 'change-request',
boundary: 'public-api-to-handler',
abuse: 'send request without a valid signature',
control: 'signed-request',
});
console.log(plan.accepted); // true
console.log(plan.controls[0].id); // signed-request
console.log(plan.evidence[0]);
// проверка отказа неподписанного учебного запроса
const rollback = rollbackTeachingThreatModel(plan);
console.log(rollback.snapshot.boundary); // public-api-to-handler
Rollback важен не как кнопка «безопасно отменить». Он проверяет другое: при отмене проекта контроля мы возвращаем исходные actor, asset, boundary и abuse, не подставляя новую историю. В production отмена может задеть ключи, миграции, compatibility, очередь, документацию и пользователей. Наша функция ничего из этого не делает. Она не должна даже имитировать deployment, иначе у читателя возникнет ложное чувство, что unit fixture покрывает операционный риск.
Откуда в этом месте появляется разработка
SSDF v1.1 полезен тем, что связывает design, implementation и verification в практиках разработки. Но в конкретном PR эти общие слова надо развернуть. Design: назвать boundary и abuse. Implementation: указать место, где handler принимает или отклоняет вход. Verification: выбрать test, который делает отрицательную ветку наблюдаемой. Change management: записать rollback и условие его запуска. Такой порядок не гарантирует отсутствие дефекта, но делает спор предметным.
Не нужно объявлять every validation security control. Иногда входной фильтр обслуживает только UX или форматирование. Связь с угрозой возникает, когда есть asset, недопустимое действие и ожидаемое защитное решение. И наоборот, не вся угроза обязана закрываться кодом process: часть требует изменения boundary, прав, операционной процедуры или отказа от функции. Модель нужна именно для различения этих случаев.
Маршрут: симптом → причина → проверка → действие
- Симптом. В PR есть control, но нет формулировки, какой негативный вход или переход он остановит.
- Причина. Разделите слова на asset, abuse, control и evidence. Если одно поле невозможно заполнить, не компенсируйте это ещё одним middleware.
- Проверка модели. Выполните fixture. Отдельно посмотрите, что assertions о missing asset, missing boundary и unknown control остаются true: они защищают договор от молчаливого угадывания.
- Действие в коде. Выберите точку принятия решения, добавьте отрицательный test именно для неё и назовите evidence в описании изменения.
- Проверка границы. Разберите, кто формирует вход до boundary и кто владеет отказом после неё. Не объявляйте local test проверкой proxy, identity provider или key management.
- Откат. До merge запишите, какой контракт и test уходят вместе с control. Если откат требует другой миграции или ключа, остановитесь и сделайте отдельный план выпуска.
Граница утверждений
Учебный контракт не применяет подпись, не обрабатывает временные окна, не хранит секреты, не проверяет права и не показывает настоящий data store. Он также не ранжирует риск и не отвечает, нужен ли signed-request в конкретном дизайне. Его единственный измеримый результат — тринадцать assertions о созданных в памяти объектах. Называть это threat modeling процесса можно только с уточнением «учебная малая модель», а не «мы провели security review».
Следующий шаг — заменить строки одним реальным контрактом команды: сделать asset и boundary именами из вашей документации, а evidence — ссылкой на разрешённый test или review. Не переносите в статью или ticket секреты, реальные request samples и имена пользователей. Достаточно того, чтобы независимый reviewer мог понять, какой отказ ожидается и какую часть изменения нужно откатить при несоответствии.
Историческая граница января 2023
NIST SP 800-154 IPD датирован 14 марта 2016 года и остаётся именно draft; NIST SP 800-218 v1.1 стал Final 3 февраля 2022 года; NIST SP 800-53 Rev. 5 издан в 2020 году. Все источники были доступны к январю 2023. Они не являются доказательством корректности данной функции или статуса безопасности внешней системы.
Проверяемые источники
- NIST SP 800-154, Initial Public Draft: Guide to Data-Centric System Threat Modeling, 14 марта 2016 — официальный датированный initial public draft, доступный к январю 2023. Это не финальная публикация; он задаёт data-centric взгляд на модель угроз, а не аттестует систему.
- NIST SP 800-218 SSDF Version 1.1, Final, 3 февраля 2022 — официальный финальный документ, доступный к январю 2023. Он описывает практики безопасной разработки; не доказывает, что конкретный код им соответствует.
- NIST SP 800-53 Revision 5, Security and Privacy Controls, September 2020 — неизменяемый официальный PDF. Каталог помогает назвать тип контроля и evidence, но сам по себе не выбирает контроль для конкретного потока.