
Привет! С вами снова Александр Симоненко, операционный директор Xilant. В первой статье трилогии о бизнес-требованиях мы разобрали, как неточные формулировки в требованиях создают уязвимости, а во второй — методики безопасных требований: INVEST, SMART, What-If и misuse-cases.
В заключительной статье поговорим о том, как встроить безопасность в процесс разработки, чтобы эти методики работали не на бумаге, а в жизни команды.
Почему методики не работают сами по себе
Даже самая правильная методика умирает в тот момент, когда она существует в вакууме, отдельно от реального процесса разработки. SMART, INVEST, What-if, misuse-cases отлично работают на бумаге, но если вокруг них нет живого контура требований, ревью, CI/CD, приемки они превращаются в красивую документацию.
Частая ситуация: команда честно заполняет шаблоны, проводит воркшопы, делает misuse-сессии, но результаты не попадают в тикеты, не отражаются в acceptance и никак не проверяются в CI. Формально «методика есть», фактически — безопасность по-прежнему держится на личной ответственности пары людей. В таком режиме любая нагрузка, дедлайн или кадровая ротация мгновенно обнуляет все усилия.
Методика начинает реально работать только тогда, когда она встроена в цепочку: «требование → acceptance → код → тесты → CI → приемка». Всё, что не доходит до этой цепочки, в прод не попадает.
Но именно эта цепочка чаще всего и рвется — не внутри шагов, а «в зазорах» между ними:
Между обсуждением и фиксацией. На встрече все правильно обсудили, придумали классные mitigations и негативные сценарии, а в user story это не попало. В тикете остается только «как партнер, я хочу…» без безопасности.
Между требованиями и разработкой. В Confluence красивый SMART, в Jira - короткий заголовок. Разработчик видит только тикет, а не исходный анализ, и реализует «как понял», а не «как задумывалось».
Между код-ревью и security-ревью. Code review смотрит на стиль, архитектуру и производительность, но не на угрозы. AppSec-ревью либо отсутствует, либо делается эпизодически, по настроению.
Между ревью и CI/CD. В ревью нашли, что нужен rate-limit и schema-validation, все согласовали, но шаг в CI, который это проверяет, так и не добавили. В результате через пару релизов кто-то случайно откатывает конфиг, и защита тихо исчезает.
Между CI и продом. В CI все зеленое, потому что тесты гоняются против одной конфигурации. В проде — другие настройки, другие секреты, другое окружение. Никакого финального security gate на выкатку нет, и уязвимость уезжает к пользователям.
По сути, провалы всегда один и тот же: то, что придумали в голове и обсудили в Zoom, не превращается в обязательный, проверяемый шаг процесса.
Чтобы безопасность перестала быть «геройством отдельных людей» и стала потоком, нужно три вещи: втащить безопасность в текст требований, , привязать безопасность к инструментам, а не к людям и ясно распределить роли.
Security Acceptance Criteria: фича считается не только рабочей, но и безопасной
Security Acceptance Criteria — это набор условий, при выполнении которых можно честно сказать: «фича реализована не только функционально, но и безопасно». Это такой же acceptance, как «кнопка нажимается и данные сохраняются», только про шифрование, доступ, логирование и тесты.
Для историй с PII или внешними интеграциями этот блок обязателен: именно такие сценарии чаще всего становятся источником утечек и инцидентов. Без него мы заранее не договариваемся, какие данные защищаем, кто имеет к ним доступ, как фиксируем действия и какими тестами проверяем выполнение. Попытки «догонять» безопасность на этапе код-ревью почти всегда заканчиваются провалом.
Если в user story нет security-acceptance, она автоматически воспринимается как чисто функциональная. Команда делает «чтобы работало», а всё, что связано с безопасностью, остаётся в голове у AppSec, в комментариях к документу, в устной договорённости. На практике: задача закрыта, тесты зелёные, но шифрование, rate-limit и негативные сценарии не проверены. На проде случается инцидент, и все удивлённо открывают исходные требования: там никакого security не было.
Структура Security Acceptance
Рассмотрим на примере, как должен выглядеть хорошо структурированный acceptance:
Scope/Объем задач: перечислить данные (name, email, phone) и покрываемые эндпоинты (/import, /user, /admin)
Это фундамент. Без этого непонятно, что мы вообще защищаем. Здесь важно честно признать PII и назвать её своими именами — иначе все остальные меры безопасности теряют смысл.
Confidential/Конфиденциальность: шифрование при хранении и в транзите; ключи в KMS; ротация ключей каждые 90 дней
Это тот слой, который спасает даже тогда, когда всё остальное ��ошло не по плану. Если здесь сэкономить, любой доступ к базе превращается в утечку. Обязательно указывать конкретные алгоритмы (AES-256-GCM), где хранятся ключи и как часто они ротируются.
Access/Доступ: аутентификация по стандарту (OAuth2/OIDC); доступ по ролям (RBAC); MFA для админ-функций; least-privilege
Практика показывает, что большинство реальных инцидентов — как раз из-за неправильного доступа, а не отсутствия шифрования. Здесь важно не просто написать «OAuth2», а указать scope токенов, какие роли имеют доступ, где требуется MFA.
Logging/Логирование: фиксировать actor / action / resource / timestamp / reason; отправлять в SIEM; хранить 365 дн.; alert при аномалиях (напр. >10 неудачных входов/мин с одного IP)
Это не только про расследование инцидентов, но и про раннее обнаружение атаки. Если ничего не логируется, вы просто не узнаете, что что-то пошло не так. Важно указать конкретные события, которые логируются, куда отправляются логи, сколько хранятся и какие условия вызывают алерты.
Test/Тесты: unit + integration; negative tests; fuzz для парсеров; все acceptance-проверки в CI перед релизом.
Производительность и соответствие: допустимое влияние на задержку (напр., медиана +50 ms); указать применимые регуляции (GDPR / PCI / ГОСТ).
Здесь превращаем слова в проверяемый результат. Если acceptance не привязан к тестам — он живёт только в документе. Производительность важна, чтобы безопасность не «убили» аргументом «слишком медленно», а регуляции показывают бизнесу прозрачную связь требований с законом.
Разделение ответственности
Без явного деления ответственности acceptance легко превращается в набор пожеланий без конкретных исполнителей. В идеале зоны распределяются так:
BA / системный аналитик описывает Scope: какие данные, какие эндпоинты, какие акторы.
AppSec формулирует требования к конфиденциальности, доступу, логированию, тестам, помогает с what-if и misuse.
Dev реализует проверку прав, валидацию, интеграцию с крипто и логированием, отвечает за корректный код.
DevOps обеспечивает шифрование at-rest, KMS, ротацию ключей, настройки TLS, интеграцию с SIEM.
QA пишет и выполняет unit, integration, negative, fuzz-тесты, проверяет, что acceptance реально покрыт тестами.
PO / PM следит, чтобы всё это было в приоритете и не «оптимизировалось» до состояния нуля при дедлайнах.
Как не превратить acceptance в формальность
Типичные ошибки: слишком об��ие формулировки без метрик («шифровать всё», «логировать важные действия»), копипаст одного и того же текста во все тикеты, отсутствие явных владельцев, acceptance никак не связан с тестами и CI.
Чтобы этого избежать, всегда спрашивайте: что именно, как проверим, кто отвечает. Оставляйте только те пункты, которые действительно будут проверяться. Не ленитесь адаптировать acceptance под конкретную фичу, а не копировать шаблон «как есть». И самое главное — сделайте так, чтобы без заполненного и осмысленного acceptance тикет невозможно было закрыть или пустить в релиз.
Threat Modelling: быстрый анализ угроз без килограмма диаграмм
В контексте требований threat modelling — это короткое упражнение «давайте честно посмотрим, где нас могут ударить». Это не многонедельный аудит с килограммом диаграмм, а структурированный здравый смысл: кто с нами взаимодействует, какие данные ходят, через какие точки всё ломается.
Мы берём будущую фичу, смотрим, какие есть акторы, потоки данных, хранилища, где границы доверия, и задаем простой вопрос: «что здесь может пойти не так и кто этим воспользуется?». Такой формат можно делать за 15–30 минут на epic и регулярно повторять. Это не разовое «большое исследование», а практический навык команды.

Процесс выглядит так: рисуем DFD level-1 — очень простую диаграмму потоков данных. Кто отправляет запросы (пользователь, партнер, бэкенд), через какие интерфейсы (API, UI, очереди), какие компоненты обрабатывают, где данные хранятся. Обозначаем границы доверия: где внешний мир, где внутренняя сеть, где особо критичные зоны.
DFD level-1 нужен не ради красоты. Он даёт команде одинаковую картинку в голове, позволяет не тратить время на сложную архитектуру и помогает быстро увидеть очевидные дырки: внешний запрос сразу в базу, нет проверки подписи, нет аутентификации между сервисами.
Дальше применяем STRIDE — чек-лист типов угроз. Берем элемент из DFD, например endpoint /import/contacts, и проверяем его по шести категориям:
Spoofing (подмена личности) — может ли кто-то выдать себя за партнёра? Есть ли OAuth2, как валидируется client_id, где хранятся секреты, можно ли подделать токен.
Tampering (изменение данных) — можно ли подменить CSV по пути? Используется ли TLS, есть ли подпись файла, проверяется ли hash.
Repudiation (отказ от совершенных действий) — можно ли отрицать, что действие совершил конкретный пользователь? Логируются ли все операции с указанием actor, timestamp и action, защищены ли логи от изменения.
Information Disclosure (утечка информации) — может ли ответ API содержать лишние данные? Маскируются ли чувствительные поля, фильтруются ли данные по правам доступа, нет ли утечки через error messages.
Denial of Service (отказ в обслуживании) — что если злоумышленник шлёт 1000 файлов по 1 ГБ? Есть ли rate-limit, size limit, используется ли очередь для обработки.
Elevation of Privilege (повышение привилегий) — можно ли через этот endpoint получить доступ к чужим данным? Настроен ли RBAC, правильно ли работает scope токена, изолированы ли данные разных пользователей.
Для каждой найденной угрозы сразу формулируем: что мы делаем, чтобы этого не произошло. Получается короткий, но конкретный список — обычно 3–5 ключевых точек, которые покрывают 80% реального риска.
Главное — не оставлять угрозы в воздухе. Для каждой угрозы нужно создавать конкретные задачи: технические mitigations (включить шифрование at-rest, добавить подпись/валидацию входящих данных, ограничить размер запросов, добавить rate-limit, усилить аутентификацию), изменения в требованиях (обновить user stories и acceptance, добавить негативные сценарии и misuse-cases), изменения в тестах и CI (добавить negative и fuzz-тесты, настроить проверки схем и конфигураций).
Если после threat modelling не появилось ни одной задачи в backlog — это был не threat modelling, а разговор на тему «как всё страшно».
Главное — после выявления угроз не оставлять их в воздухе. Для каждой угрозы нужно созда��ать конкретные задачи:
Технические mitigations: включить шифрование at-rest, добавить подпись и валидацию входящих данных, ограничить размер запросов, настроить rate-limit, усилить аутентификацию.
Изменения в требованиях: обновить user stories и security acceptance, добавить негативные сценарии и misuse-cases.
Изменения в тестах и CI: добавить negative и fuzz-тесты, настроить проверки схем и конфигураций.
Если после threat modelling не появилось ни одной задачи в бэклоге, значит, это был не threat modelling, а просто разговор «как все страшно».
Теперь посмотрим, как конкретно внедрить методики в процесс, чтобы обсуждения и анализ рисков превращались в реально реализуемые user stories с проверяемыми security-требованиями.
Walkthrough: 5 шагов от плохого требования к готовой user story
Наша цель проста: превратить обсуждения, чек-листы и What-if сценарии в готовую user story с Security Acceptance и назначенными владельцами.

Лучше всего это делать в таком порядке:
Сначала понять, о чём вообще задача (scope).
Пока не ясно, какие данные, кто актор и куда всё записывается, говорить о безопасности бессмысленно. Это фундамент.Затем проверить, не забыли ли мы базовые элементы (чек-лист).
Это быстрый скан: есть ли шифрование, доступ, логирование, тесты. Чек-лист не даёт пропустить очевидное.Потом чуть глубже копнуть через What-if.
Это помогает увидеть не только «чего нет», но и «во что это выльется в реальности» - атаки на парсер, обход авторизации, утечки.После этого сформировать новую, нормальную user story с acceptance.
Здесь всё знание упаковывается в артефакт, которым уже можно пользоваться в Jira и CI.И в конце не забыть завести отдельные задачи на mitigations.
Иначе все договоренности так и останутся в описании.
Разберем walkthrough на часто встречающемся кейсе «импорт контактов партнера».
Исходная (плохая) user story. «Как партнёр, я хочу загружать CSV с контактами.»
Шаг 1 — Прочитать и понять scope (1 мин)
Вопросы: какие поля в CSV? кто загружает (партнёр/админ)? куда сохраняются данные? это PII?
Результат: Scope = name, email, phone; endpoints = POST /import/contacts; PII = да.и
Именно здесь часто вскрывается первая серия проблем: внезапно оказывается, что никто до конца не понимает, какие поля есть в CSV, это точно PII или «просто контакты», куда именно все сохраняется.
Шаг 2 — Применить чек-лист (2 мин)
Чек-лист: есть ли Scope, Confidentiality, Auth, Logging, Tests, Performance, Compliance?
Scope — есть (определили).
Confidentiality — нет (нужно добавить шифрование для PII).
Auth — не указано (надо OAuth2 + roles).
Logging — не указано.
Tests — нет.
Шаг 3 — Прогнать 3 What-if (2–3 мин)
Первый: что если партнёр загрузит специально сформированный CSV? → риск: parser exploit → mitigation: schema validation + sandbox.
Второй: что если файл пройдёт без авторизации? → риск: массовый слив → mitigation: OAuth2 и role checks + rate-limit.
Третий: что если PII сохраняется в открытом виде? → риск: утечка → mitigation: at-rest encryption + KMS, key rotation.
Шаг 4 — Сформировать исправленное требование + acceptance (2 мин)
Хорошая (готовая для тикета) user story (copy-paste):
Title: Partner contacts import — secure flow
Description: Система должна позволять партнёрам загружать CSV с контактами (поля: name, email, phone) через защищённый API POST /import/contacts.
Acceptance / Security checks: Доступ к endpoint — только по OAuth2; токены scope = partner_import; rate-limit = 100 requests/min.
Файл проходит schema-validation и size limit 10 MB; парсинг выполняется в изолированном sandbox.
PII поля сохраняются зашифрованными at-rest (AES-256-GCM); ключи в KMS; ротация ключей каждые 90 дней.
Logging: запись события загрузки (actor, file_id, record_count, timestamp); отправка логов в SIEM; retention 365 d.
Tests: unit tests for parser, integration test for end-to-end import, fuzz tests for parser; CI-job запускает проверку schema и симуляцию ротации ключей.
Owners: Dev — реализация парсера; AppSec — ревью mitigations; QA — подготовка negative tests; DevOps — KMS key management. Estimate: 5 story-points (примерно 1 sprint).
Шаг 5 — Создать задачи на mitigations и назначить (1 мин)
Создать таск: «Добавить schema validation + sandbox для import parser» (owner = Dev, acceptance = тесты, due = sprint X).
Создать таск: «Включить encryption at-rest for PII + CI key rotation test» (owner = DevOps + AppSec).
Рекомендации для максимально хорошего результата:
Делать walkthrough командой: BA + Dev + QA + AppSec. В одиночку всегда что-то упустишь.
Ставить жесткий лимит по времени: 8–12 минут на историю, чтобы не превратить это в бесконечное обсуждение.
Фиксировать результат в готовой user story и acceptance, а не «просто обсудили».
Каждый негативный сценарий должен порождать либо конкретное acceptance-условие, либо отдельную задачу на mitigation.
Приучить команду, что без такого walkthrough истории с PII и интеграциями просто не попадают в разработку.
Roadmap: встраиваем безопасность в процесс за 90 дней
Следующий шаг — смотреть на поток разработки в целом. Чтобы процесс работал стабильно, а не зависел от усилий отдельных людей, я советую следующий 90-дневный roadmap.

Неделя 1–2: Security Acceptance Template + обязательные поля
Сначала нужно заставить безопасность появиться в требованиях как стандартный элемент, а не как исключение. Добавляем Security Acceptance Template в шаблоны задач и делаем его обязательной частью требования. Любая серьезная user story не попадает в работу, пока блок про безопасность не заполнен.
Главное здесь — не создать формальность. Шаблон должен бы��ь коротким и конкретным, а не «мини-ISO-стандартом». Поля делаем обязательными для заполнения — иначе их просто будут пропускать. В шаблоне не должно быть пунктов, которые команда заведомо не проверяет — иначе все превратится в галочки. Назначаем одного владельца (обычно AppSec или BA Lead), который следит за качеством заполнения.
Чтобы шаблон реально работал: привязываем поля acceptance к конкретным действиям — тестам, конфигам, настройкам CI. Включаем простую проверку: тикет нельзя закрыть, пока acceptance не заполнен. Раз в спринт делаем короткий разбор-полетов — смотрим 2–3 тикета, как реально выполняются acceptance. Периодически чистим шаблон: если пункт ни разу не применяли или не проверяли — либо убираем, либо делаем осмысленным.
Неделя 3–4: тренинг BA/PO — чек-лист + what-if
Теперь учим тех, кто пишет требования, видеть риски еще на уровне формулировок. Проводим 2-часовой практический воркшоп для BA/PO/Dev/QA: как использовать чек-лист и запускаем what-if сессию. Результат: user stories сразу рождаются более качественными, а не «сырой текст, который потом поправит AppSec».
Лучше всего работают воркшопы, построенные на реальных кейсах команды, а не абстрактных примерах. Берем 2–3 актуальные user stories и прямо на сессии прогоняем по чек-листу и what-if. Делаем это вслух, с комментариями — чтобы BA/PO услышали мышление AppSec и Dev. Фиксируем лучшие формулировки в живой библиотеке примеров. Ограничиваем разбор каждого кейса 10–15 минутами, чтобы команда фокусировалась на сути.
Типичные сложности с misuse-сессиями: люди боятся «думать как злоумышленник» и уходят в фантастику или, наоборот, ничего не предлагают. Команда пытается покрыть все возможные атаки, и сессия затягивается на часы. Всё обсудили, но ничего не попало в backlog.
Подробнее misuse-сессии и what-if мы разбирали во второй статье цикла о требованиях.
Месяц 2 — lightweight threat modelling для текущих эпиков
Выводим понимание угроз на уровень эпиков и архитектуры.
Для 3 текущих эпиков проводим lightweight threat modelling (15–30 мин каждый) и настраиваем pre-merge CI job, который проверяет наличие security-fields и базовые правила.
Threat modelling здесь не про тяжелые сессии — он должен быть легким, повторяемым и встроенным в рутину. Если же после сессии не изменился ни backlog, ни архитектура, ни CI — это был разговор «для галочки».
Когда threat modelling начинает работать, важно параллельно настроить CI-проверки, которые будут автоматически ловить очевидные проблемы. Здесь тоже есть свои правила.
Чтобы CI-проверки реально помогали, а не мешали:
Начинайте с простого: schema-validation, size limit, базовый линтинг конфигов.
Делайте проверки быстрыми, чтобы они не тормозили pipeline.
Разделяйте блокирующие и предупреждающие проверки: не всё должно падать билд.
Давайте разработчикам понятные сообщения об ошибках и инструкции, как исправить.
Следите за % ложных срабатываний - если их много, проверки будут игнорировать или отключать.
Месяц 3 — автоматизация (CI jobs, basic regex/NLP), метрики и dashboard
Убираем избыточный ручной контроль и делаем безопасность частью инженерной рутины. Разворачиваем базовый дашборд с метриками: процент требований с заполненным security-acceptance, lead-time на исправление security-issues, количество misuse cases per epic. Добавляем первые simple CI-tests (schema check job, simple fuzz job).
Самое сложное на этом этапе — подобрать правильный уровень детализации: не перегрузить CI, но и не сделать игрушечным, и поддерживать проверки в актуальном состоянии, когда меняется архитектура, требования, стеки.
Самое полезное: автоматическое замечание «ты забыл acceptance» на этапе создания тикета, базовые проверки схем и конфигураций в CI, снятие метрик — сколько историй прошли security-check, сколько упали, сколько уязвимостей поймал pipeline до прода.
Какие метрики отслеживать?
% user stories с заполненным security acceptance
% историй, прошедших все security-проверки в CI
число найденных и закрытых mitigations за спринт
время от обнаружения угрозы до реализации mitigation
количество инцидентов/находок на проде, связанных с требованиями (или их отсутствием)
Эти цифры хорошо показывают, движемся ли мы от «реактивной» к «проактивной» безопасности.
При внедрении roadmap команды часто совершают одни и те же ошибки. Самая распространенная — попытка сразу внедрить «идеальный» процесс, что приводит к перегрузке.
Другие типичные проблемы: шаблоны делают слишком тяжелыми и непрактичными, всю ответственность вешают на одного AppSec-человека, или запускают CI-проверки, которые постоянно ломают билды и вызывают раздражение.
Как этого избежать? Главное — двигаться итеративно: сначала acceptance, потом чек-листы, потом threat modelling, потом автоматизация. Начинать стоит с самых болезненных зон: PII, деньги, интеграции. Важно заранее договариваться о приоритетах и SLA на security-задачи, а на каждом этапе проводить ретроспективу и упрощать то, что не работает.
И еще несколько «золотых правил»:
Если в user story есть PII или интеграция, без security acceptance она не существует.
Если mitigation не попал в backlog - он не будет сделан.
Если проверка не встроена в CI - её будут забывать.
Если нет владельца - нет ответственности.
Если процесс нельзя пройти за 10–15 минут - он не будет выполняться регулярно.
Соблюдение этих простых принципов даёт гораздо больше эффекта, чем любая «идеальная» методика, оторванная от реальной жизни команды.
Мы прошли полный путь: от понимания, почему методики умирают без процесса, до конкретного 90-дневного roadmap внедрения.
Главное — помнить, что безопасность требований работает только тогда, когда она встроена в поток разработки. Шаблоны, чек-листы и воркшопы — это инструменты, но реальная ценность появляется, когда они становятся частью ежедневной работы команды.
Разделение ролей, прозрачные процессы и автоматизация превращают безопасность из декларации в проверяемый результат. Каждый новый функционал проходит через одни и те же шаги, и только тогда риск инцидентов минимизируется. Безопасность — это свойство процесса, а не отдельная задача.
Спасибо, что дочитали трилогию до конца. Надеюсь, что вам было интересно, а самое главное полезно — подписывайтесь на мой канал «Крупицы знаний» и на канал Xilant. Будем на связи!