Опирается на правила: R-SEC-FIND-1R-SEC-FIND-3 и R-SEC-FIND-X1 из Security Style Guide → раздел 6. Реакция на findings.

Важно знать

  • CRITICAL → сборка падает, hotfix < 24 часов.
  • HIGH → сборка падает, патч ≤ 2 недели (текущий спринт).
  • MEDIUM → отчёт, патч ≤ 30 дней.
  • LOW → игнорим, не отображаем в dashboard.
  • Suppression без until= — не считается suppressed, считается долгом.
  • GitHub Code Scanning / SARIF — единый dashboard через GitHub Security tab.
  • «Не уверен, эксплуатируется ли» — добавляй suppression с обоснованием. Молчание = долг.

Findings — это входящий поток работы для security backlog. UCP формулирует SLA per severity, чтобы команда не тонула в noise (LOW) и быстро реагировала на критичное. Без SLA findings накапливаются, dashboard становится «море красного», команда привыкает.

Severity → SLA

R-SEC-FIND-1: четыре уровня, четыре действия.

SeverityИнструментыSLA на исправлениеБлокирует
CRITICALлюбой< 24 часаСборка падает, hotfix immediate
HIGHSpotBugs / FindSecBugs / Trivy / DepCheck≤ 2 недели (sprint)Сборка падает
MEDIUMSpotBugs / FindSecBugs / Trivy≤ 30 днейОтчёт, не блокирует
LOWлюбойИгнор, не отображается

CRITICAL — hotfix < 24 часа

Примеры:

  • Active exploit известный (Log4Shell-уровень).
  • Hardcoded prod credential leaked.
  • Critical CVE с public PoC в active runtime dependency.

Action plan:

  1. Алерт security-team немедленно.
  2. Создание hotfix branch.
  3. Применение patch / temporary mitigation.
  4. Deploy в проде в течение 24 часов.
  5. Post-mortem.

HIGH — текущий спринт

Примеры:

  • CVE с CVSS 7.0-8.9 в зависимости.
  • SQLi pattern в новом коде.
  • Missing @PreAuthorize на admin endpoint.

Action plan:

  • Создание ticket с label security/high.
  • Включение в текущий спринт.
  • Прогон через PR review до merge.
  • Deploy с next release.

MEDIUM — 30 дней

Примеры:

  • CVE с CVSS 4.0-6.9.
  • SpotBugs EI_EXPOSE_REP в нелегаси коде.
  • Trivy finding в OS package без active exploit.

Action plan:

  • Ticket с label security/medium.
  • Включение в один из следующих спринтов.
  • Если за 30 дней не fixed — auto-escalate до HIGH.

LOW — игнор

Примеры:

  • SpotBugs style findings (URF_UNREAD_FIELD).
  • Theoretical CVE без known exploitation vector.
  • Trivy finding в test dependency.

Не отображаем в дашборде. Не создаём ticket. Не тратим время.

Suppressions имеют срок

R-SEC-FIND-2: until= обязателен везде.

<!-- dependency-check-suppressions.xml -->
<suppress until="2026-08-01Z">
    <notes>CVE-2024-XXXX: false positive в transitive dep, не в runtime path. Ждём fix в upstream library 2.5.</notes>
    <cve>CVE-2024-XXXX</cve>
</suppress>
<!-- spotbugs-exclude.xml -->
<Match>
    <!-- justify: legacy code path, refactor запланирован
         до: 2026-09-30 -->
    <Class name="ru.vikulinva.legacy.OldHandler"/>
    <Bug pattern="MS_MUTABLE_COLLECTION"/>
</Match>

Раз в квартал — auto-script ищет просроченные suppressions:

#!/bin/bash
# tools/check-expired-suppressions.sh
NOW=$(date +%Y-%m-%d)
xmllint --xpath '//suppress[@until]' config/dependency-check-suppressions.xml |
  while read entry; do
    until=$(echo "$entry" | grep -oP 'until="\K[^"]+')
    if [[ "$until" < "$NOW" ]]; then
      echo "EXPIRED: $entry"
    fi
  done

CI прогоняет этот script weekly, постит issue в repo.

Без срока — suppression становится «забытым исключением». Через 2 года никто не помнит, почему добавили, security team не может ревью.

GitHub Code Scanning + SARIF

R-SEC-FIND-3: единый dashboard.

Все инструменты UCP экспортируют SARIF format (Static Analysis Results Interchange Format):

# CI step
- name: Upload SpotBugs SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: build/reports/spotbugs/main.sarif

- name: Upload Trivy SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: trivy-results.sarif

- name: Upload Dependency-Check SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: build/reports/dependency-check-report.sarif

После — все findings видны в GitHub Security tab:

  • Filter по severity, tool, file.
  • Tracking фикса (status: open / dismissed / fixed).
  • Notifications в Slack/PagerDuty через GitHub.

Без отдельной инфры (SonarQube, Snyk dashboard) — встроено в GitHub.

Альтернатива для GitLab — GitLab Security Dashboard, тоже принимает SARIF.

«Не уверен, эксплуатируется ли»

R-SEC-FIND-X1: главный антипаттерн.

Security tool: "SQL_INJECTION_JDBC at OrderRepository.java:142"
Developer: "Ну вроде там getValidatedId(), это безопасно"
[ничего не делает]
[через год attacker эксплуатирует]

Что должно произойти:

<!-- spotbugs-exclude.xml -->
<Match>
    <!-- justify: getValidatedId() возвращает только Long, проверен через @Valid @Min(1)
                  на DTO-уровне; реального string concat нет. False positive SpotBugs из-за
                  ${} в SQL template (это JPQL parameter, не interpolation).
         до: 2026-09-30 (пересмотреть после миграции на jOOQ типизированные queries) -->
    <Class name="ru.vikulinva.order.OrderRepository"/>
    <Method name="findByCustomerAndStatus"/>
    <Bug pattern="SQL_INJECTION_JDBC"/>
</Match>

Это:

  • Запись в репо — security team может ревью.
  • Срок — повторная проверка через 6 месяцев.
  • Обоснование — explicit аргумент.

«Молчание = долг» — finding в дашборде остаётся, suppression нет → security team тратит время на повторный анализ, каждое review дублирует работу.

Baseline-механика

R-SEC-4: релиз блокируется только на новые findings.

# config/security-baseline.json — обновляется на каждом merge в main
{
  "dependencyCheck": {
    "knownVulnerabilities": [
      {"cve": "CVE-2024-12345", "package": "...", "firstSeen": "2026-03-15"}
    ]
  }
}

При release tag — сравниваем findings с baseline:

  • Новый CVE → блокируем release.
  • CVE уже в baseline → не блокируем (это долг, отдельная задача).

Без baseline первый протухший CVE в transitive dep остановит pipeline на неделю — команда начнёт игнорировать всю security. Baseline отделяет «долг» от «новое».

Что запрещено

АнтипаттернПравилоЧто взамен
Игнорирование finding без suppressionR-SEC-FIND-X1suppression с обоснованием
Suppression без until=R-SEC-FIND-2срок обязателен
CRITICAL не hotfix immediatelyR-SEC-FIND-1< 24 часа
HIGH в backlog «когда-нибудь»R-SEC-FIND-1≤ 2 недели
MEDIUM игнорируется без срокаR-SEC-FIND-1≤ 30 дней, auto-escalate если не fixed
LOW отображается в дашбордеR-SEC-FIND-1не показываем
Findings в proprietary tool без SARIFR-SEC-FIND-3GitHub Code Scanning через SARIF
Baseline не updates на mergeR-SEC-4auto-update на main
Просроченные suppressions не trekаютсяR-SEC-FIND-2weekly script

Куда дальше

  • Security → раздел 6. Реакция на findings — нормативные формулировки.
  • SAST по коду — suppressions в spotbugs-exclude.xml.
  • CVE в зависимостях — suppressions в dependency-check-suppressions.xml.
  • Секреты в коде и истории — leak = CRITICAL, rotate immediately.
  • Container/image-уязвимости — Trivy SARIF в Security tab.
  • Криптография в коде — weak crypto = HIGH.
  • Observability → SLO и алерты — security alerts отдельный канал.