Материал

Policy gate без бюрократии: что блокировать автоматически, а что выпускать с risk acceptance

Рабочая схема приоритизации critical / high / medium, роли согласования и примеры правил, которые защищают релиз — но не бесят команду

Почему policy gate — это не про запреты, а про скорость принятия решений

Когда инженер видит в CI-пайплайне красный флаг, у него три варианта: исправить, проигнорировать или попросить кого-то разобраться. Третий вариант — это и есть бюрократия в своём худшем виде: ожидание, неясность ответственности, давление дедлайна.

Исследование Checkmarx 2025 года зафиксировало тревожный тренд: 98% компаний сообщили об инцидентах, связанных с уязвимым кодом, при этом 81% организаций намеренно выпускают код с известными уязвимостями, чтобы уложиться в сроки [1]. Для сравнения — два года назад таких было около двух третей [3]. Это не халатность. Это системный сбой в процессе принятия решений.

Параллельно растёт другая проблема — alert fatigue. Согласно данным Splunk State of Observability 2025, 43% инженеров тратят избыточное время на реагирование на алерты, а 73% организаций сталкивались с инцидентами из-за проигнорированных предупреждений [4]. Когда каждый PR сопровождается десятками предупреждений, команда перестаёт их читать. Gate, который блокирует всё, фактически не блокирует ничего — разработчики находят способ обойти или игнорировать его.

Задача policy gate в DevSecOps — не максимизировать количество блокировок, а минимизировать время, которое уходит на понимание, можно ли выпускать конкретное изменение прямо сейчас.

Почему CVSS не работает как единственный критерий

Интуиция подсказывает: берём CVSS 9.0+ — блокируем. Берём CVSS 7.0+ — блокируем с оговорками. Всё остальное — пропускаем. Эта схема понятна, легко объяснима менеджменту, и она не работает в production.

Исследование, опубликованное на arxiv в 2025 году, показало: только около 20% уязвимостей с оценкой "critical" или "high" по CVSS когда-либо эксплуатировались в реальных атаках, при этом именно high-severity оценки получают примерно 57% от всех опубликованных уязвимостей [2]. Получается: следуя только CVSS, команда тратит ресурсы на патчинг теоретических рисков и оставляет незакрытыми уязвимости, которые атакующие активно используют.

CVSS по своей природе — это метрика технической тяжести, а не бизнес-риска [5]. Она не знает:

  • Доступна ли уязвимая функция из интернета или только из внутренней сети.
  • Есть ли у уязвимости публичный proof-of-concept и находится ли она в каталоге CISA Known Exploited Vulnerabilities (KEV).
  • Реально ли вызывается уязвимый код вашим приложением (reachability).
  • Насколько критичен сервис с точки зрения бизнеса.

Практика лидирующих команд — комбинировать несколько сигналов. CVSS даёт базовую тяжесть. EPSS (Exploit Prediction Scoring System, поддерживается FIRST) оценивает вероятность эксплуатации в ближайшие 30 дней. CISA KEV фиксирует факт реальной эксплуатации в живых атаках. Reachability-анализ (доступен в некоторых SCA-инструментах) отвечает на вопрос: вызывается ли этот путь кода вообще. По данным Semgrep, анализ reachability для зависимостей увеличивает fix rate с 67% до 92% у лидирующих команд — разрыв принципиальный [6].

Это не значит, что нужно строить сложную формулу. Это значит, что правила gate должны учитывать хотя бы контекст: наличие эксплойта, среду развёртывания, критичность сервиса.

Три уровня policy gate: hard block, risk acceptance, pass with warning

Рабочая модель, которую используют зрелые DevSecOps-команды, делит все findings на три категории. Важно, что это не статическая разметка "всегда блокировать CVE-2024-XXXX", а решение, принимаемое в контексте конкретного изменения и конкретного релиза.

Уровень 1: Hard block — автоматически, без исключений

Это то, что никогда не должно попасть в production при любых обстоятельствах. Правила этого уровня — недискуссионны и должны быть зашиты в gate в виде машинно-проверяемых политик.

Признаки hard block:

  • Секрет (API-ключ, токен, пароль, приватный ключ) найден непосредственно в коде или конфигурационном файле, который коммитится в репозиторий.
  • SQL-инъекция или другой класс уязвимостей OWASP Top 10 с прямой цепочкой от внешнего ввода до опасной операции, без валидации.
  • Уязвимость с CVSS 9.0+ и наличием подтверждённого эксплойта в CISA KEV на компонент, который непосредственно доступен из сети.
  • Отсутствие аутентификации на endpoint'е, который по спецификации должен её иметь.
  • Образ контейнера из неавторизованного реестра или без подписи — если это правило принято в компании.
  • Изменение настроек безопасности CI/CD-файла (например, GITHUB_TOKEN с write-правами, отключение branch protection) без явного согласования.

Пример правила в GitHub Actions (псевдокод):

- name: Block hardcoded secrets
  uses: trufflesecurity/trufflehog@main
  with:
    fail_on_findings: true

Пример в логике OPA (Rego):

deny[msg] {
  input.finding.type == "secret_in_code"
  msg := sprintf("Hard block: secret detected in %v", [input.finding.file])
}

Результат на уровне PR: merge заблокирован. Разработчик получает сообщение: "Секрет найден в файле X, строка Y. Удалите секрет, поместите его в vault/env. Инструкция: [ссылка]." Никакого согласования не нужно — правило применяется автоматически.

Уровень 2: Risk acceptance — пропустить с явным согласованием

Это находки, которые несут реальный риск, но по объективным причинам не могут быть исправлены немедленно. Ключевое слово — "объективным". Risk acceptance — это не способ откладывать неудобное на потом. Это формализованное решение с владельцем, сроком и планом исправления.

Признаки risk acceptance:

  • Уязвимость CVSS 7.0–8.9 (high) без публичного эксплойта, при наличии компенсирующего контроля (например, сервис за WAF, доступ только из VPN).
  • Уязвимость в транзитивной зависимости, для которой нет фикса от upstream и нет прямого пути эксплуатации в вашем коде.
  • Уязвимость в deprecated-компоненте, который заменяется в рамках запланированной миграции в следующем спринте.
  • Временно ослабленная конфигурация (например, расширенный CORS или debug-режим) для hotfix, с обязательным тикетом на откат.

Требования к risk acceptance:

  1. Письменное обоснование: почему нельзя исправить сейчас.
  2. Компенсирующий контроль: что снижает риск до исправления.
  3. Дата окончания: до которой риск должен быть закрыт (обычно 14–30 дней для high, до 90 дней для medium).
  4. Владелец: конкретный человек, который отвечает за закрытие.
  5. Тикет в системе управления задачами: с привязкой к релизу и автоматическим напоминанием.

Согласование risk acceptance — не перформанс безопасности. Это механизм, при котором решение о риске принимает человек с соответствующими полномочиями, а не тот, кто оказался рядом в момент дедлайна.

Уровень 3: Pass with warning — выпустить, зафиксировать в backlog

Для находок medium и ниже, не имеющих публичных эксплойтов и затрагивающих некритичные компоненты, правильное решение — пропустить, сгенерировать тикет и не мешать деливери. Блокировать medium-уязвимость в зависимости, которая используется только в dev-инструментах и никогда не попадает в production-образ, — это ровно тот тип gate, который "бесит команду".

Признаки pass with warning:

  • CVSS ниже 7.0, нет эксплойта в KEV.
  • Уязвимость в компоненте, который не разворачивается в production.
  • Проблема code quality класса "потенциально плохая практика", без прямой цепочки эксплуатации.

Результат: PR проходит, в тикет-трекер автоматически создаётся задача с владельцем и приоритетом, на dashboard AppSec видно накопленный технический долг.

Роли согласования: RACI для policy gate

Одна из главных причин бюрократии в security gate — отсутствие заранее определённых ролей. Когда не ясно, кто имеет право подписать risk acceptance, находка висит в ожидании, пока дедлайн не вынуждает кого-то принять решение наугад. По данным ReversingLabs, именно отсутствие чёткого RACI приводит к тому, что решения о принятии риска де-факто принимают инженеры под давлением дедлайна, без участия безопасников [7].

Рабочая RACI для policy gate:

Для hard block:

  • Responsible: инструмент (автоматически).
  • Accountable: Tech Lead команды — отвечает за то, что правило не обходится.
  • Consulted: AppSec-инженер — если правило вызывает сомнение в применимости.
  • Informed: Engineering Manager.

Для risk acceptance (high severity):

  • Responsible: разработчик — готовит обоснование.
  • Accountable: AppSec-инженер или Security Champion команды — подписывает решение.
  • Consulted: Tech Lead — оценивает технические компенсирующие контроли.
  • Informed: CISO (для продуктов с высоким уровнем защиты данных).

Для risk acceptance (critical severity, если всё-таки возникает):

  • Responsible: Tech Lead.
  • Accountable: CISO или VP Engineering.
  • Consulted: Legal/Compliance, если затронуты персональные данные или платёжная информация.
  • Informed: CEO, если риск затрагивает весь продукт.

Для pass with warning (medium и ниже):

  • Responsible: инструмент (автоматически создаёт тикет).
  • Accountable: разработчик, чей PR создал находку.
  • Informed: Tech Lead, AppSec.

Принципиально важно: роли должны быть документированы в runbook и известны до начала релизного цикла, а не выясняться в момент блокировки.

Примеры конкретных правил

Правила, приведённые ниже, основаны на практиках, описанных в руководствах OWASP, документации Semgrep и Microsoft, а также на публичных DevSecOps-практиках [8][9][10].

Правила hard block (всегда блокировать):

  1. Любой секрет (regex на ключи AWS/GCP/Azure, токены GitHub, Slack, Stripe) в коде или в tracked конфигурации — блокировать с указанием файла, строки и инструкции по перемещению в secrets manager.
  1. SQL-инъекция через конкатенацию строк в любом query-методе, без подготовленных выражений — блокировать, предлагать параметризованный запрос.
  1. Зависимость с CVE из CISA KEV при CVSS 9.0+ и отсутствии workaround — блокировать, указывать доступную версию с фиксом или альтернативу.
  1. Dockerfile FROM latest без pinning — предупреждение с возможностью блокировки в production-образах.
  1. Изменение .github/workflows с добавлением secrets: inherit или permissions: write-all без явного review от AppSec — блокировать.
  1. Debug-флаги или явные backdoor-паттерны (например, if user == "admin123") в production-ветке — блокировать.

Правила risk acceptance (high, требуют обоснования):

  1. Транзитивная зависимость с CVSS 7.0–8.9, нет прямого вызова уязвимой функции (non-reachable) — принять с тикетом на 30 дней, указав, что reachability проверена.
  1. Слишком широкий CORS (allow all origins) в dev-окружении, если branch не идёт в production — принять с комментарием в PR и тикетом на устранение до следующего релиза.
  1. Устаревший алгоритм хэширования (MD5, SHA1) в некритичном контексте (например, ID генерации без security-функции) — принять с явным комментарием, что функция не используется для паролей или подписей.

Правила pass with warning (medium/low):

  1. Уязвимость в dev-зависимости, не попадающей в production-образ — создать тикет, не блокировать.
  1. Устаревший, но не эксплуатируемый пакет без CVE — занести в техдолг, не блокировать.
  1. Потенциально опасный паттерн с высоким false positive rate — показать как informational, не блокировать без ручного подтверждения.

Как устроить согласование без бюрократии: операционные принципы

Бюрократия возникает не от наличия процесса, а от его плохого дизайна. Несколько принципов, которые снижают трение:

SLA на ответ, а не на закрытие. AppSec-команда должна ответить на запрос risk acceptance за 4–8 рабочих часов, а не "когда освободится". Само закрытие уязвимости может занять 30 дней, но ответ "принято / не принято" — нет.

Решение по умолчанию для типовых кейсов. Если уязвимость уже была принята через risk acceptance в предыдущем цикле для аналогичного контекста, в pipeline должна быть возможность сослаться на предыдущее решение, а не проходить полный цикл заново.

Самообслуживание для medium и ниже. Tech Lead или Security Champion команды должны иметь право самостоятельно закрыть risk acceptance для medium-уязвимостей, не привлекая AppSec. AppSec видит решение в audit log и может оспорить — но не является блокером по умолчанию.

Автоматическое истечение. Risk acceptance автоматически истекает в дату, зафиксированную при выдаче. По истечении — находка возвращается в hard block до нового цикла согласования. Это убирает ситуацию, когда "временное" решение живёт годами.

Один канал, а не десять. Все запросы на risk acceptance идут через один инструмент (тикет в Jira/Linear с фиксированным template или комментарий в PR с bot-ответом). Это убирает параллельные переписки в Slack, которые никто не трекирует.

Объяснение, а не просто блок. Сообщение в CI должно содержать: что найдено, почему это блок, что нужно сделать, ссылку на документацию. "Security policy violation" без деталей — это не gate, это саботаж деливери.

Где policy gate часто ломается

Слишком много hard block для medium. Классическая ошибка — перенести всё CVSS 7.0+ в автоматический блок. Результат: разработчики начинают искать способы отключить проверку или ставить suppress-комментарии без анализа, потому что другого пути нет.

Risk acceptance без срока. Принятый риск без даты истечения — это риск, о котором забудут. По данным Help Net Security, некоторые Non-KEV уязвимости в среднем остаются неисправленными более 1.7 лет [11].

Согласование без полномочий. Если AppSec-инженер одного уровня должен согласовывать с другим AppSec-инженером, а решение нигде не фиксируется, — это имитация процесса.

Gate только в CI, не в PR. Разработчик узнаёт о проблеме на этапе merge в main вместо этапа push своей feature-ветки. Это увеличивает стоимость исправления и создаёт ощущение "охоты на ведьм" перед релизом.

Отсутствие reachability-фильтрации. Блокировать зависимость, уязвимый код которой никогда не вызывается — это создание шума. Лидирующие команды по данным Semgrep fix на non-reachable findings показывают fix rate 67% против 92% для reachable [6]. Разница — это избыточный noise, который проедает доверие к gate.

Игнорирование конфигурационных файлов и CI/CD. Атаки на supply chain в 2025 году всё активнее направлены на компрометацию CI/CD-pipeline — например, инцидент с GitHub Actions tj-actions/changed-files в начале 2025 года показал, как одно изменение в workflow-файле может привести к утечке секретов во всех downstream-репозиториях [12]. Gate, который проверяет только application-код и игнорирует .github/workflows, Dockerfile, конфиги terraform и k8s-манифесты, — неполный gate.

Policy as Code: инфраструктура для правил, которые можно поддерживать

Самая распространённая альтернатива Policy as Code — правила в Wiki или spreadsheet, которые "все знают, но никто не проверяет". Проблема понятна: такие правила не применяются автоматически, устаревают незаметно, и при конфликте превращаются в предмет политической дискуссии.

Policy as Code переводит правила в машинно-исполняемые артефакты, которые версионируются в репозитории, покрываются тестами и применяются единообразно.

Open Policy Agent (OPA) — CNCF-graduated проект — позволяет писать политики на декларативном языке Rego и применять их в Kubernetes-admission контроле, CI/CD pipeline, Terraform plan validation и API Gateway [13]. Базовая структура правила:

package release.policy

deny[msg] {
  vuln := input.findings[_]
  vuln.severity == "critical"
  vuln.has_public_exploit == true
  msg := sprintf("Hard block: %v has public exploit", [vuln.cve_id])
}

warn[msg] {
  vuln := input.findings[_]
  vuln.severity == "high"
  not vuln.has_public_exploit
  msg := sprintf("Risk acceptance required for %v", [vuln.cve_id])
}

HashiCorp Sentinel выполняет аналогичную функцию для Terraform Cloud/Enterprise — позволяет валидировать инфраструктурные изменения до apply [14].

Ключевое преимущество Policy as Code — rules живут в том же репозитории (или в отдельном, но версионированном), что и код. Изменение правила требует PR, ревью и CI-прогона. Споры "кто решает" снимаются: правило либо существует в коде, либо нет.

Контроль изменений в эпоху AI-кодинга

Отдельного внимания заслуживает контекст 2025 года: большая часть кода, который попадает на review, теперь сгенерирована или отредактирована AI-ассистентами. По данным Checkmarx, большинство разработчиков уже используют AI для написания кода, при этом большинство организаций не имеют формализованной политики в отношении AI-инструментов [1].

AI-generated код несёт специфические риски, которые традиционный gate часто не покрывает:

  • Package hallucinations: AI может порекомендовать несуществующий пакет, который злоумышленник уже успел зарегистрировать под этим именем.
  • Устаревшие паттерны: модели обучены на исторических данных и могут воспроизводить deprecated API или известные уязвимые паттерны.
  • Конфиги с широкими правами: AI часто генерирует permissions: write-all или * в IAM-политиках "для простоты".
  • Секреты в примерах: AI-ассистент может вставить placeholder, который выглядит как реальный токен и срабатывает на детекторе секретов.

Это значит, что gate для AI-сгенерированного кода должен уделять особое внимание именно тем категориям, которые AI воспроизводит систематически: секреты, конфиги, зависимости, CI/CD-файлы.

Именно здесь дополнительный слой контроля до merge имеет смысл: не ещё один SAST-отчёт с сотней findings, а анализ конкретного изменения в конкретном контексте с коротким ответом — можно ли безопасно принять именно этот PR прямо сейчас. По своей сути это и есть то, чего не хватает большинству команд: не больше инструментов, а понятный ответ на уровне конкретного дифа прямо перед merge.

Одним из инструментов, который строится именно вокруг этой логики, является HighVibe. Это дополнительный слой контроля безопасности для команд, которые уже ускорили разработку с AI, — не замена SAST, SCA или другим инструментам AppSec-стека, а прослойка между ними и моментом merge. HighVibe анализирует конкретный диф: новые и обновлённые зависимости, изменения конфигурационных файлов, CI/CD-скриптов, служебного кода и миграций — то, что в обычном PR-ревью дочитывают реже всего. Вместо длинного отчёта после релиза команда получает короткий сигнал до merge: что именно вызывает вопрос, почему это важно и каков следующий шаг — исправить, пересмотреть или остановить слияние. Это особенно актуально для тех категорий, которые AI-ассистенты воспроизводят систематически и которые сложнее всего поймать в ручном ревью под дедлайн.

Метрики, по которым стоит оценивать gate

Gate без обратной связи — это black box. Команда должна видеть, работает ли он, не создаёт ли лишнего трения, не пропускает ли реальные риски.

Метрики, которые стоит трекать:

  1. False positive rate по правилам hard block — если выше 10–15%, правило нужно уточнять или переводить в warn.
  2. Среднее время ответа на risk acceptance запрос — целевое значение: до 8 рабочих часов.
  3. Процент risk acceptance, которые закрыты в срок — если ниже 70%, даты нереалистичны или ответственность не назначена.
  4. Количество suppress-комментариев без обоснования — рост этой метрики = gate превращается в формальность.
  5. Fix rate по critical SAST-блокам — по данным Semgrep, если ниже 50%, проблема не в качестве детекции, а в workflow между детекцией и ремедиацией [6].
  6. Процент релизов с активными risk acceptance — если выше 30% релизов выходят с несколькими открытыми risk acceptance, это сигнал, что правила hard block поставлены слишком агрессивно или команда недоинвестировала в исправление.

Заключение: gate как инструмент доверия, а не контроля

Policy gate работает, когда команда считает его своим инструментом, а не внешним ограничением. Это достигается через три вещи.

Прозрачность: все правила известны заранее, доступны в репозитории, изменяются через тот же процесс, что и code review.

Предсказуемость: разработчик знает, что будет заблокировано, что потребует согласования, а что пройдёт с комментарием — до того, как открывает PR.

Скорость: ответ на risk acceptance за часы, а не дни. Hard block с понятным шагом к разблокировке, а не просто "security violation".

По данным Google Cloud Accelerate State of DevOps 2024, команды с полностью автоматизированными pipeline'ами восстанавливаются после security-инцидентов на 45% быстрее, чем те, кто использует ручные ревью-gates [15]. Автоматизация не означает отсутствие контроля — она означает, что контроль работает по расписанию, а не по настроению.

Хороший policy gate защищает релиз. Плохой — задерживает его без объяснений. Разница между ними — не в инструментах, а в дизайне правил и процессе согласования.

Источники

[1] Checkmarx. Future of Application Security in the Era of AI (2025) — https://checkmarx.com/resources/reports/

[2] Kowalczyk N. et al. Vulnerability Management Chaining: An Integrated Framework for Efficient Cybersecurity Risk Prioritization. arxiv.org, 2025 — https://arxiv.org/abs/2506.01220

[3] Cybersecurity Dive. Developers knowingly push vulnerable code, despite growing breach risk (Aug 2025) — https://www.cybersecuritydive.com/news/software-vulnerabilities-breaches-checkmarx-report/757793/

[4] Splunk. State of Observability 2025 — https://www.splunk.com/en_us/form/state-of-observability.html

[5] Tenable. What is CVSS? — https://www.tenable.com/cybersecurity-guide/principles/common-vulnerability-scoring-system-cvss

[6] Semgrep. Remediation at Scale (2025/2026, данные по 50,000+ репозиториям) — цит. по The Hacker News — https://thehackernews.com/expert-insights/2026/03/which-code-vulnerabilities-actually-get.html

[7] ReversingLabs. Deadlines vs. secure code: What AppSec teams can do (Sep 2025) — https://www.reversinglabs.com/blog/deadlines-vs-secure-code

[8] OWASP. OWASP Top 10 — https://owasp.org/www-project-top-ten/

[9] Matthias Rohr. How Security Gates Can Work Efficiently Even with DevOps (Nov 2023) — https://matthiasrohr.de/2023/11/24/how-security-gates-can-work-efficiently-even-with-devops/

[10] Microsoft. DevSecOps on AKS: Governance Gates That Actually Prevent Incidents (2025) — https://techcommunity.microsoft.com/blog/azureinfrastructureblog/devsecops-on-aks-governance-gates-that-actually-prevent-incidents/4508415

[11] Help Net Security. What 2024 taught us about security vulnerabilities (Jan 2025) — https://www.helpnetsecurity.com/2025/01/14/cybersecurity-vulnerabilities-2024/

[12] Silobreaker. 12 Months That Changed Supply Chain Security (Dec 2025) — https://www.silobreaker.com/blog/cyber-threats/supply-chain-attacks-in-2025-a-month-by-month-summary/

[13] Open Policy Agent. Documentation — https://www.openpolicyagent.org/docs/latest/

[14] Spacelift. Top 12 Policy as Code Tools in 2026 — https://spacelift.io/blog/policy-as-code-tools

[15] Fyld. 2025 Complete Guide to DevSecOps for Agile Teams (Oct 2025) — https://www.fyld.pt/blog/2025-guide-to-devsecops-for-agile-teams/

FAQ

Быстрые вопросы по теме

Что такое policy gate?

Это система, которая управляет процессом релиза, минимизируя бюрократию.

Каковы уровни policy gate?

Существуют три уровня: hard block, risk acceptance и pass with warning.

Что такое hard block?

Это автоматическая блокировка релиза при наличии критических уязвимостей.

Как работает risk acceptance?

Это формализованное решение о выпуске с учетом рисков и сроков исправления.

Когда следует использовать pass with warning?

Для уязвимостей medium и ниже, не влияющих на критичные компоненты.

Нужен такой же контроль в ваших изменениях и релизах?

Покажем пример такого замечания на вашем сценарии и соберём пилотный контур без лишней суеты.

Запросить пилот Все статьи
Дальше по теме

Ещё материалы

Все статьи
04 мая 2026 17 мин release gate

Release gate на основе SBOM и KEV: как за 30 секунд получить ответ «можно ли выпускать»

Один релиз — один сигнал. Не отчёт на 400 строк, а одно решение: зелёный или красный. TL;DR SBOM — машиночитаемый список всех компонентов сборки. Без него невозможно знать, что именно уходит в прод. KEV — каталог CISA с…

Открыть материал
02 мая 2026 21 мин AI

Как безопасно принимать AI-сгенерированный код перед merge: практический diff-based чек-лист

Подзаголовок: Что смотреть в коде, конфиге, lock файлах и служебных файлах — и когда достаточно комментария, а когда нужен жёсткий стоп TL;DR AI сгенерированный код содержит в 2,74 раза больше уязвимостей, чем написанны…

Открыть материал
28 апреля 2026 18 мин AI

Как выбрать инструмент контроля AI-кодинга: 12 вопросов к вендору перед пилотом

Коммерческий спрос на инструменты контроля AI кодинга дорос до уровня, когда недостаточно просмотреть демо и прочитать лендинг. Нужен структурированный разговор с вендором — до того, как вы потратите три месяца на пилот…

Открыть материал