Как защитить конвейер CI/CD с помощью CodeMender

1. Подготовка

Добро пожаловать на практическую работу Защита конвейера CI/CD с помощью CodeMender.

В современной разработке ПО инструменты статического анализа, такие как CodeQL, необходимы для выявления известных синтаксических шаблонов. Однако они часто пропускают уязвимости, скрытые глубоко в бизнес-логике, и генерируют множество непроверенных оповещений.

CodeMender (исполняемый файл CLI: cm) улучшает конвейер CI/CD, работая вместе с существующими инструментами SAST. Он развертывает агенты логического анализа безопасности на базе Gemini от Google, чтобы:

Обнаружение сложных ошибок в бизнес-логике. Анализ контекста приложения и архитектурных потоков данных, выходящий за рамки жестких статических правил шаблонов.

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

Автономно устранять подтвержденные проблемы. Создавать исправления кода, проверять их с помощью наборов тестов, чтобы предотвратить регрессии, и отправлять готовые к проверке pull-запросы.

В этой практической работе вы интегрируете CodeMender в хранилище OWASP Juice Shop с помощью GitHub Actions и федерации Workload Identity Google Cloud (WIF) без ключей.

Требования

  • Рекомендуется: базовое понимание принципов работы CodeMender (рассматривается в курсе Защита приложений с помощью CodeMender).
  • Базовое понимание рабочих процессов, триггеров и синтаксиса YAML в GitHub Actions.
  • Базовые знания о командах Git и рабочих процессах проверки pull-запросов.
  • Базовые знания о концепциях Google Cloud IAM (сервисные аккаунты, роли и API).
  • Знание распространенных уязвимостей веб-приложений (например, внедрение SQL-кода и XSS).

Что вы узнаете

  • Как настроить аутентификацию без ключа с нулевым доверием между GitHub Actions и Google Cloud с помощью Workload Identity Federation (WIF)
  • Как создать автоматизированный рабочий процесс поиска уязвимостей с помощью CodeMender и gemini-3.8-flash
  • Как публиковать отчеты о безопасности, на основе которых можно принимать меры, используя OASIS SARIF v2.1.0 и встроенные сводки заданий GitHub Actions.
  • Как создать автономный рабочий процесс исправления, который генерирует проверенные тестами исправления кода и открывает Pull-запросы для проверки специалистом.
  • Как применять автоматизированные жесткие ограничения качества (--fail-on) и кеширование конвейера для высокоскоростной непрерывной безопасности

Что вам понадобится

  • Проект Google Cloud с включенными платежными функциями и разрешениями владельца или редактора проекта.
  • Аккаунт GitHub с разрешениями на создание репозиториев, настройку Секретов и управление действиями (на шаге 3 вы создадите ответвление репозитория OWASP Juice Shop GitHub с помощью GitHub CLI).

2. Архитектура непрерывной интеграции и развертывания CodeMender

В современных корпоративных DevSecOps безопасность на основе искусственного интеллекта не может быть просто ручным инструментом для настольных компьютеров. Он должен работать как автоматизированный привратник (блокировать небезопасные pull-запросы) и автономный соразработчик (предлагать проверенные исправления непосредственно в Git).

Для этого вы реализуете архитектуру с двумя рабочими процессами на основе федерации Workload Identity Google Cloud (WIF) и моделей рассуждения Gemini Enterprise.

Архитектура с двумя рабочими процессами

Архитектура автономного конвейера CI/CD CodeMender

Вместо того чтобы объединять обнаружение и устранение в один монолитный скрипт, конвейер разделяет безопасность на два отдельных специализированных рабочих процесса:

Рабочий процесс

Основной триггер

Основные обязанности

Строгие требования к качеству

1. Сканер уязвимостей(codemender-scan.yml)

Pull-запросы, основные пуши, еженедельный cron, отправка вручную

• Быстрое дифференциальное сканирование AST в запросах на извлечение (около 15 секунд), быстрое базовое сканирование при отправке (–quick) и параллельные глубокие аудиты по расписанию.• Проверка готовности с помощью cm health –strict.• Создание сводок по заданиям Actions и загрузка OASIS SARIF на вкладку безопасности GitHub.

Блокирует слияние запросов на извлечение, если обнаружены новые уязвимости высокого или критического уровня (–fail-on).

2. Автономный инструмент устранения неполадок(codemender-remediate.yml)

Запуск вручную (workflow_dispatch), еженощный запуск cron

• Возобновляет работу с артефактами сканирования (cm report import) и state.db• Синтезирует исправления, используя логику Gemini• Сохраняет границы рабочей области и отправляет готовые к проверке pull-запросы

Обеспечивает чистые различия в рабочей среде перед открытием PR.

Три основных принципа проектирования корпоративных систем

При создании этих рабочих процессов в следующих разделах помните о трех основных принципах архитектуры:

🔑 Аутентификация без ключа с нулевым доверием и предварительная проверка

В GitHub Secrets не хранятся долгосрочные JSON-ключи сервисного аккаунта Google Cloud. Исполнитель генерирует кратковременный токен OIDC, который обменивается через Google Cloud STS на временные учетные данные, действующие в течение часа, устанавливает persist-credentials: false для извлечений Git и запускает cm health --strict, чтобы проверить учетные данные, сетевую доступность и разрешения IAM, прежде чем использовать квоту модели.

⚡ Адаптивная маршрутизация сканирования и устаревшее шумоподавление

Вместо того чтобы выполнять медленные полные проверки репозитория для каждого pull-запроса, CodeMender направляет каждое событие непрерывной интеграции в оптимальный режим сканирования. Pull-запросы запускают дифференциальный анализ AST (--diff="origin/$BASE_REF") измененных файлов и вызывающих объектов за один шаг менее чем за 15 секунд. При отправке в основную ветку выполняются быстрые базовые сканирования за один сеанс (--quick). По еженедельному расписанию запускаются параллельные глубокие проверки каждого файла (по умолчанию cm find .). Существующие уязвимости базы кода, не затронутые pull-запросом, помечаются как [LEGACY / UNTOUCHED]. Они отображаются в отчетах SARIF, но не блокируют слияние pull-запроса и не запускают автоматическое исправление.

🛡️ Надежная неблокирующая наблюдаемость безопасности

Даже если --fail-on завершает работу с кодом 1, чтобы заблокировать небезопасный запрос на извлечение, защита экспорта отчетов и загрузки SARIF с помощью steps.scan.outputs.completed == 'true' и hashFiles('results.sarif') != '' гарантирует, что оповещения OASIS SARIF и сводки заданий по-прежнему будут публиковаться. При этом экспорт и загрузка будут пропущены, если выполнение отменено или прервано из-за ошибки настройки или емкости (10–60).

3. Выполните аутентификацию и подготовьте целевое хранилище в Cloud Shell

Чтобы настроить аутентификацию без ключа и запустить автоматизированные конвейеры безопасности, вам нужен доступный целевой репозиторий GitHub, которым вы владеете. В этой практической работе вы будете использовать OWASP Juice Shop – веб-приложение Node.js, в котором намеренно оставлены уязвимости, – в качестве готовой среды для тестирования безопасности.

Вы будете использовать интерфейс командной строки GitHub (gh), предустановленный в Google Cloud Shell, чтобы выполнить аутентификацию в GitHub, автоматически получить сведения о пользователе и подготовить хранилище в рамках одного оптимизированного процесса.

Шаг 1. Откройте Cloud Shell и выполните аутентификацию GitHub CLI

Откройте консоль Google Cloud и активируйте Cloud Shell (значок >_ на верхней панели навигации).

Выполните аутентификацию GitHub CLI (gh), чтобы настроить управление учетными данными Git:

gh auth login --hostname github.com --git-protocol https --web

Следуйте инструкциям на экране:

Скопируйте восьмизначный одноразовый код, который появится в Cloud Shell (например, 1234-ABCD).

Нажмите Ввод, чтобы открыть https://github.com/login/device в браузере.

Вставьте код и нажмите Authorize github (Авторизовать GitHub).

Шаг 2. Динамически экспортируйте переменные и создайте форк OWASP Juice Shop

Чтобы автоматически получить имя пользователя GitHub и подготовить репозиторий, выполните в Cloud Shell следующие команды:

# 1. Automatically capture your GitHub username (customize GITHUB_REPO if desired)
export GITHUB_ORG=$(gh api user -q .login)
export GITHUB_REPO="${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_ORG:+${GITHUB_ORG}/${GITHUB_REPO}}"
echo "Authenticated as: ${GITHUB_REPOSITORY}"

# 2. Fork on GitHub server using GITHUB_REPO as the fork name
gh repo fork juice-shop/juice-shop --fork-name "${GITHUB_REPO}" --default-branch-only --clone=false 2>/dev/null || true

# 3. Shallow clone your fork (downloads only ~15 MB in 3-5 seconds, skipping heavy upstream git history)
[ -d ~/"${GITHUB_REPO}" ] || git clone --depth=1 "https://github.com/${GITHUB_REPOSITORY}.git" ~/"${GITHUB_REPO}" || \
 (sleep 2 && git clone --depth=1 "https://github.com/${GITHUB_REPOSITORY}.git" ~/"${GITHUB_REPO}")
cd ~/"${GITHUB_REPO}"

# 4. Confirm you are in the repository directory
git status

4. Как настроить интеграцию идентификационных данных рабочих нагрузок Google Cloud с помощью gcloud

На этом шаге вы будете использовать CLI gcloud в Google Cloud Shell, чтобы включить необходимые API, создать специальный сервисный аккаунт CI/CD, настроить пул Workload Identity и установить доверие OIDC с вашим репозиторием GitHub (${GITHUB_REPOSITORY}).

Шаг 1. Настройте переменные среды Google Cloud

В терминале Cloud Shell (в рабочей области клонированного хранилища) получите идентификатор активного проекта Google Cloud, проверьте переменную хранилища GitHub и определите названия ресурсов WIF:

# Capture active Google Cloud Project ID and verify GitHub repository
export PROJECT_ID=$(gcloud config get-value project)
export GITHUB_USER=$(gh api user -q ".login")
export GITHUB_REPO="${GITHUB_REPO:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*/##; s#\.git$##')}"
export GITHUB_REPO="${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_USER:+${GITHUB_USER}/${GITHUB_REPO}}"

# Define WIF and Service Account resource names
export WORKLOAD_IDENTITY_POOL="codemender-github-pool"
export WORKLOAD_IDENTITY_PROVIDER="codemender-github-provider"
export SERVICE_ACCOUNT_NAME="codemender-ci-runner"

if [ -z "${PROJECT_ID}" ] || [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: PROJECT_ID ('${PROJECT_ID}') or GITHUB_REPOSITORY ('${GITHUB_REPOSITORY}') is empty. Check 'gcloud config get-value project' and 'gh auth status'."
else
 echo "Project ID:        ${PROJECT_ID}"
 echo "GitHub Repository: ${GITHUB_REPOSITORY}"
fi

Шаг 2. Включите необходимые API Google Cloud

Включите IAM API, Security Token Service API, IAM Credentials API, Agent Platform API и Resource Manager API.

gcloud services enable \
 iam.googleapis.com \
 iamcredentials.googleapis.com \
 sts.googleapis.com \
 aiplatform.googleapis.com \
 cloudresourcemanager.googleapis.com \
 --project=${PROJECT_ID}

Шаг 3. Создайте специальный сервисный аккаунт CI/CD

Создайте сервисный аккаунт Google Cloud с минимальными привилегиями, предназначенный для выполнения конвейера CI/CD (или используйте существующий):

export SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud iam service-accounts describe "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" >/dev/null 2>&1 || \
gcloud iam service-accounts create "${SERVICE_ACCOUNT_NAME}" \
 --display-name="CodeMender CI/CD Pipeline Runner" \
 --project="${PROJECT_ID}"

echo "Service Account Email: ${SERVICE_ACCOUNT_EMAIL}"

Шаг 4. Предоставьте разрешения IAM для Agent Platform

Предоставьте сервисному аккаунту роль roles/aiplatform.user (пользователь платформы агентов), чтобы он мог взаимодействовать с Gemini Enterprise Agent Platform.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
 --role="roles/aiplatform.user"

Шаг 5. Создайте пул Workload Identity

Создайте пул Workload Identity, чтобы управлять утверждениями идентификационных данных GitHub Actions (или автоматически восстановите и включите его, если он уже существует в вашем проекте):

POOL_STATE=$(gcloud iam workload-identity-pools list \
 --location="global" \
 --show-deleted \
 --project="${PROJECT_ID}" \
 --filter="name ~ /${WORKLOAD_IDENTITY_POOL}$" \
 --format="value(state)")

if [ -z "${POOL_STATE}" ]; then
 gcloud iam workload-identity-pools create "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --display-name="CodeMender GitHub Pool" \
   --project="${PROJECT_ID}"
else
 [ "${POOL_STATE}" = "DELETED" ] && gcloud iam workload-identity-pools undelete "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --project="${PROJECT_ID}"
 gcloud iam workload-identity-pools update "${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --no-disabled \
   --project="${PROJECT_ID}"
fi

Шаг 6. Создайте поставщика Workload Identity с помощью GitHub OIDC

Создайте или обновите поставщика OIDC в пуле, связав URL издателя https://token.actions.githubusercontent.com и сопоставив утверждения токена GitHub с атрибутами Google STS:

PROVIDER_STATE=$(gcloud iam workload-identity-pools providers list \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --show-deleted \
 --project="${PROJECT_ID}" \
 --filter="name ~ /${WORKLOAD_IDENTITY_PROVIDER}$" \
 --format="value(state)")

if [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: GITHUB_REPOSITORY is empty. Re-run Step 1 before configuring the OIDC provider."
elif [ -z "${PROVIDER_STATE}" ]; then
 gcloud iam workload-identity-pools providers create-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --display-name="CodeMender GitHub Provider" \
   --issuer-uri="https://token.actions.githubusercontent.com" \
   --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
   --attribute-condition="assertion.repository == '${GITHUB_REPOSITORY}'" \
   --project="${PROJECT_ID}"
else
 [ "${PROVIDER_STATE}" = "DELETED" ] && gcloud iam workload-identity-pools providers undelete "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --project="${PROJECT_ID}"
 gcloud iam workload-identity-pools providers update-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
   --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
   --location="global" \
   --issuer-uri="https://token.actions.githubusercontent.com" \
   --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
   --attribute-condition="assertion.repository == '${GITHUB_REPOSITORY}'" \
   --no-disabled \
   --project="${PROJECT_ID}"
fi

Шаг 7. Разрешите хранилищу GitHub выдавать себя за сервисный аккаунт

Привяжите роль roles/iam.workloadIdentityUser, чтобы разрешить токенам из вашего хранилища выдавать себя за сервисный аккаунт исполнителя непрерывной интеграции, и проверьте привязку политики:

# Retrieve the canonical Workload Identity Pool resource ID
export POOL_ID=$(gcloud iam workload-identity-pools describe "${WORKLOAD_IDENTITY_POOL}" \
 --project="${PROJECT_ID}" \
 --location="global" \
 --format="value(name)")

if [ -z "${POOL_ID}" ] || [ -z "${GITHUB_REPOSITORY}" ]; then
 echo "ERROR: POOL_ID ('${POOL_ID}') or GITHUB_REPOSITORY ('${GITHUB_REPOSITORY}') is empty. Re-run Step 1 and Step 5."
else
 # Bind Workload Identity User role to the principalSet of your repository
 gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT_EMAIL}" \
   --project="${PROJECT_ID}" \
   --role="roles/iam.workloadIdentityUser" \
   --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${GITHUB_REPOSITORY}"

 # Verify the principalSet binding on the Service Account
 gcloud iam service-accounts get-iam-policy "${SERVICE_ACCOUNT_EMAIL}" \
   --project="${PROJECT_ID}"
fi

Шаг 8. Получите значения конфигурации для секретов GitHub

Получите полное название ресурса поставщика Workload Identity и сохраните его в переменной среды для автоматической регистрации на следующем шаге:

# Retrieve full Workload Identity Provider name
export WORKLOAD_PROVIDER_NAME=$(gcloud iam workload-identity-pools providers describe ${WORKLOAD_IDENTITY_PROVIDER} \
 --workload-identity-pool=${WORKLOAD_IDENTITY_POOL} \
 --location="global" \
 --project=${PROJECT_ID} \
 --format="value(name)")

echo "=========================================================="
echo "WIF CONFIGURATION READY:"
echo "=========================================================="
echo "GCP_WORKLOAD_IDENTITY_PROVIDER: ${WORKLOAD_PROVIDER_NAME}"
echo "GCP_SERVICE_ACCOUNT:            ${SERVICE_ACCOUNT_EMAIL}"
echo "=========================================================="

5. Как настроить секреты репозитория GitHub и разрешения рабочего процесса

Теперь, когда федерация идентификационной информации Google Cloud настроена, вы настроите секреты репозитория GitHub и предоставите необходимые разрешения рабочего процесса для автоматического сканирования безопасности и автоматического исправления pull-запросов.

Вы можете задать эти настройки прямо в Cloud Shell с помощью GitHub CLI (gh), чтобы не копировать и не вставлять вручную длинные названия ресурсов.

Шаг 1. Настройте секреты хранилища с помощью GitHub CLI

В терминале Cloud Shell выполните следующие команды, чтобы безопасно задать два необходимых секрета хранилища с помощью активных переменных среды:

# 1. Set the Workload Identity Provider resource name
gh secret set GCP_WORKLOAD_IDENTITY_PROVIDER \
 --body "${WORKLOAD_PROVIDER_NAME}" \
 --repo "${GITHUB_REPOSITORY}"

# 2. Set the CI/CD Service Account email
gh secret set GCP_SERVICE_ACCOUNT \
 --body "${SERVICE_ACCOUNT_EMAIL}" \
 --repo "${GITHUB_REPOSITORY}"

# 3. Verify the secrets are registered
gh secret list --repo "${GITHUB_REPOSITORY}"

Шаг 2. Предоставьте разрешения на рабочие процессы для автоматических запросов на извлечение

По умолчанию рабочие процессы GitHub Actions выполняются с разрешениями только на чтение и не могут создавать pull-запросы. На шаге 9 CodeMender автоматически создаст и отправит проверенные pull-запросы на исправление.

Предоставьте разрешения на запись и разрешите создание pull-запросов напрямую через GitHub API:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"

gh api \
 --method PUT \
 -H "Accept: application/vnd.github+json" \
 /repos/${GITHUB_REPOSITORY}/actions/permissions/workflow \
 -f default_workflow_permissions="write" \
 -F can_approve_pull_request_reviews=true

Шаг 3. Отключите унаследованные рабочие процессы Juice Shop

При создании форка OWASP Juice Shop переносятся 16 рабочих процессов непрерывной интеграции (например, PR Compliance Check, CI/CD Pipeline и CodeQL Scan), а также шаблон запроса на извлечение от стороннего разработчика, который автоматически закрывает запросы на извлечение, нацеленные на master. Отключите все рабочие процессы, кроме CodeMender, с помощью GitHub CLI и удалите вышестоящие файлы локально, чтобы в вашем форке выполнялись только рабочие процессы CodeMender:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"

# 1. Disable all inherited non-CodeMender workflows in GitHub Actions (and CodeQL default setup if active)
for WF_ID in $(gh workflow list --all --limit 100 --repo "${GITHUB_REPOSITORY}" --json id,path \
 -q '.[] | select((.path | startswith(".github/workflows/")) and (.path | test("codemender-") | not)) | .id'); do
 gh workflow disable "${WF_ID}" --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
done
gh api -X PATCH "/repos/${GITHUB_REPOSITORY}/code-scanning/default-setup" \
 -f state=not-configured >/dev/null 2>&1 || true

# 2. Remove upstream workflow files and PR template from the local workspace
for f in .github/workflows/*; do
 case "$f" in *codemender-*) ;; *) rm -f "$f" ;; esac
done
rm -f .github/PULL_REQUEST_TEMPLATE.md

6. Как создать автоматизированный рабочий процесс поиска уязвимостей с помощью SARIF

На этом шаге вы создадите основной рабочий процесс непрерывного сканирования безопасности (.github/workflows/codemender-scan.yml), который выполняет базовое сканирование при отправке ветвей, дифференциальные проверки в pull-запросах и экспорт SARIF в GitHub Code Scanning.

Шаг 1. Скачайте рабочий процесс сканирования CodeMender

Скачайте codemender-scan.yml из репозитория starter в .github/workflows/:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
mkdir -p .github/workflows
curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-scan.yml \
 -o .github/workflows/codemender-scan.yml

Шаг 2. Зафиксируйте и отправьте изменения, а также запустите сканирование непрерывной интеграции

Зафиксируйте изменения рабочего процесса и отправьте их непосредственно в основную ветвь репозитория (master для Juice Shop или main):

# Stage workflow changes, commit, and push to primary branch
git add -A .github
git commit -m "ci: add CodeMender SARIF security scanning workflow"
git push origin $(git branch --show-current)

В браузере:

Перейдите в свое хранилище GitHub: https://github.com/YOUR_GITHUB_USER/juice-shop (например, https://github.com/octocat/juice-shop).

Нажмите на вкладку Действия на верхней панели навигации.

На боковой панели слева в разделе Workflows (Рабочие процессы) выберите CodeMender Security Scan & SARIF Export (Сканирование безопасности CodeMender и экспорт SARIF).

Запустите или посмотрите выполнение рабочего процесса:

Автоматический триггер. Если в списке есть автоматический запуск, активированный вашим push-уведомлением, нажмите на него, чтобы отслеживать выполнение в реальном времени.

Запуск по запросу (workflow_dispatch). Если запуск ещё не начался, нажмите кнопку Run workflow (Запустить рабочий процесс) ▾ справа, убедитесь, что выбрана ветка Branch: master (не устанавливайте флажок deep_scan, чтобы запустить быстрое базовое сканирование --quick), и нажмите зеленую кнопку Run workflow (Запустить рабочий процесс).

Нажмите на выполняемый запуск и выберите Autonomous Code Vulnerability Scan (Автономный поиск уязвимостей в коде), чтобы посмотреть, как рабочий процесс запускается в реальном времени.

Файл codemender-scan.yml: маршрутизация сканирования на основе событий

Пока базовое сканирование --quick выполняется в облаке (около 3–5 минут), посмотрите, как codemender-scan.yml (строки 118–155) направляет каждое событие GitHub в соответствующий режим сканирования в средстве запуска:

# Excerpt from .github/workflows/codemender-scan.yml
if [ "${{ github.event_name }}" = "pull_request" ]; then
 cm find . \
   --diff="origin/${{ github.base_ref }}" \
   --diff-workers=16 \
   --fail-on="CRITICAL,HIGH" \
   --sandbox=false --yes --bypass-warning || status=$?
elif [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event.inputs.deep_scan }}" = "true" ]; then
 cm find . \
   --deep-workers=8 \
   --sandbox=false --yes --bypass-warning || status=$?
else
 cm find . \
   --quick \
   --sandbox=false --yes --bypass-warning || status=$?
fi

Hardened Runner Setup ( строки 27–117): пропускает ненадежные внешние форки и запросы на извлечение dependabot[bot], извлекает с помощью persist-credentials: false, кеширует ~/.local/bin/cm и ~/.codemender/state.db и запускает cm health --strict перед использованием квоты модели.

Границы изолированной среды без графического интерфейса (--sandbox=false --yes --bypass-warning). Отключает изоляцию пространства имен пользователей Linux (ограничено в непривилегированных контейнерах GitHub Actions), сохраняя границы путей рабочей области (project_paths) и command_policy.yaml.

Экспорт SARIF и артефактов с защитой по коду выхода ( строки 147–194). Задает steps.scan.outputs.completed=true, только если cm find завершается с кодом 0 (чисто) или 1 (достигнут порог --fail-on). Это гарантирует, что отчеты SARIF (cm report -f sarif с оценками серьезности CVSS), таблицы $GITHUB_STEP_SUMMARY (cm report -f md) и артефакты codemender-findings.json по-прежнему публикуются, когда --fail-on блокирует запрос на извлечение, а экспорт пропускается при ошибках настройки или емкости (10–60), поэтому пустые файлы SARIF никогда не закрывают существующие оповещения.

7. Как проверять оповещения о сканировании кода GitHub и панель управления безопасностью

После завершения рабочего процесса отправки базового плана GitHub обрабатывает загруженный файл SARIF и заполняет сводку выполнения действий и вкладку "Безопасность" репозитория.

Шаг 1. Проверьте сводку по задаче в GitHub Actions

При каждом запуске рабочего процесса сводная таблица Markdown (cm report -f md) добавляется непосредственно в обзор запуска GitHub Actions:

В репозитории GitHub откройте вкладку Actions (Действия).

Выберите завершенный запуск CodeMender Security Scan & SARIF Export (проверки базовой ветви завершаются зеленой галочкой ✅ после публикации результатов SARIF).

Прокрутите вниз до раздела 🛡️ CodeMender Security Scan Summary (Сводка по сканированию безопасности CodeMender), чтобы посмотреть подробные результаты.

🔒 Отчет о безопасности CodeMender

Общие сведения

Всего результатов: 28

Уровень

Счетчик

🔴 КРИТИЧЕСКИЙ

6

🟠 ВЫСОКИЙ

16

🟡 СРЕДНИЙ

6

Статус

Счетчик

🔴 ОТКРЫТО

28

Результаты

Идентификатор

Уровень

Уверенность

Статус

Исправить

Файл

Название

c1b96b9a

🔴 КРИТИЧЕСКИЙ

100%

ОТКРЫТЬ

—

routes/userProfile.ts

Удаленное выполнение кода через внедрение кода на стороне сервера в профиле пользователя

cd47b38a

🔴 КРИТИЧЕСКИЙ

100%

ОТКРЫТЬ

—

routes/login.ts

Внедрение SQL-кода в маршрут аутентификации пользователя

a47a9e45

🔴 КРИТИЧЕСКИЙ

100%

ОТКРЫТЬ

—

routes/b2bOrder.ts

Удаленное выполнение кода через выход из изолированной среды при обработке заказов B2B

Шаг 2. Изучите централизованную панель управления сканированием кода

На верхней панели навигации в репозитории GitHub нажмите на вкладку Security and quality (Безопасность и качество) или Security (Безопасность).

На боковой панели слева в разделе Findings (Результаты) выберите Code scanning (Сканирование кода).

Если активно несколько инструментов, отфильтруйте Инструмент по CodeMender (is:open branch:master tool:CodeMender), чтобы проверить оповещения, сопоставленные со значками серьезности CVSS:

Значок уровня серьезности

Заголовок уязвимости

Определенное местоположение

Branch

🔴 Критическая

Удаленное выполнение кода через внедрение кода на стороне сервера в профиле пользователя

routes/userProfile.ts:58

master

🔴 Критическая

Внедрение SQL-кода в маршрут аутентификации пользователя

routes/login.ts:34

master

🔴 Критическая

Удаленное выполнение кода через выход из изолированной среды при обработке заказов B2B

routes/b2bOrder.ts:21

master

Нажмите SQL Injection in User Authentication Route (SQL-инъекция в маршруте аутентификации пользователя) (routes/login.ts:34), чтобы посмотреть поток зараженных данных и анализ основной причины, выполненный Gemini.

8. Как заблокировать небезопасный pull-запрос с помощью дифференциального сканирования

Базовое сканирование выявило 28 уязвимостей в OWASP Juice Shop. При использовании традиционных статических анализаторов эти 28 устаревших результатов приводили бы к сбою каждого последующего pull-запроса, пока не был бы исправлен весь бэклог, что вынуждало бы команды отключать блокировку слияния.

Теперь вы протестируете PR Differential AST Gate (--diff + --fail-on="CRITICAL,HIGH") в CodeMender. Вы откроете pull-запрос, который создает новую уязвимость, и посмотрите, как CodeMender изолирует дельту, блокирует слияние примерно за 15–25 секунд и аннотирует строки, в которых есть уязвимость.

Шаг 1. Создайте pull-запрос, который добавляет уязвимость к внедрению команд

В Cloud Shell (в рабочей области клонированного репозитория) создайте ветку функции, добавьте новый маршрут Express, содержащий уязвимость внедрения команд ОС, и откройте pull-запрос для своего форка:

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
PRIMARY_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@')

# Reset any previous demo PR/branch so this step can be re-run cleanly
gh pr close feat/diagnostics --repo "${GITHUB_REPOSITORY}" --delete-branch 2>/dev/null || true
git checkout "${PRIMARY_BRANCH}"
git checkout -B feat/diagnostics

# Introduce an Express endpoint vulnerable to OS Command Injection (CWE-78)
cat << 'EOF' > routes/diagnostics.ts
import { execSync } from 'node:child_process'
import { type Request, type Response } from 'express'

export function systemDiagnostics () {
 return (req: Request, res: Response) => {
   const host = String(req.query.host ?? '127.0.0.1')
   const output = execSync(`ping -c 1 ${host}`).toString()
   res.status(200).json({ status: 'ok', output })
 }
}
EOF

git add routes/diagnostics.ts
git commit -m "feat: add network diagnostics endpoint"
git push -f -u origin feat/diagnostics

gh pr create \
 --repo "${GITHUB_REPOSITORY}" \
 --base "${PRIMARY_BRANCH}" \
 --head feat/diagnostics \
 --title "feat: add network diagnostics endpoint" \
 --body "Adds a ping diagnostics handler."

Шаг 2. Проверьте шлюз слияния дифференциальных изменений и встроенную аннотацию запроса на извлечение

Откройте URL pull-запроса, указанный в конце выходных данных терминала.

Прокрутите страницу обсуждения pull-запроса вниз до раздела Checks (Проверки) и найдите Autonomous Code Vulnerability Scan (Автономный поиск уязвимостей в коде).

Скорость дельта-сканирования. Вместо сканирования всех 680+ файлов в репозитории (около 3–5 минут) cm find . --diff="origin/${PRIMARY_BRANCH}" анализирует только routes/diagnostics.ts (и все вызывающие объекты в пределах одного перехода), завершая сканирование за 15–25 секунд.

Изоляция устаревших уязвимостей и блокировка слияния. Ни одна из 28 нетронутых устаревших уязвимостей Juice Shop не приводит к сбою проверки. Только новая уязвимость CRITICAL (внедрение команд) активирует --fail-on="CRITICAL,HIGH" и завершает работу с кодом статуса 1 (красный крестик ❌), блокируя слияние запроса на извлечение.

В верхней части страницы pull-запроса нажмите на вкладку Files changed (Измененные файлы).

Поскольку защита кода выхода рабочего процесса (steps.scan.outputs.completed == 'true') по-прежнему экспортирует и загружает results.sarif, когда --fail-on завершает работу с кодом 1, GitHub Code Scanning отображает встроенную аннотацию безопасности CodeMender – критическая непосредственно под execSync в routes/diagnostics.ts.

Шаг 3. Удалите тестовый запрос на извлечение и вернитесь к основной ветке

Прежде чем переходить к автономному исправлению, переключите рабочую область Cloud Shell обратно на основную ветвь и закройте небезопасный тестовый pull-запрос.

[ -d .git ] || cd ~/"${GITHUB_REPO:-juice-shop}"
export GITHUB_REPOSITORY="${GITHUB_REPOSITORY:-$(git remote get-url origin 2>/dev/null | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
PRIMARY_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@')
git checkout "${PRIMARY_BRANCH}"
gh pr close feat/diagnostics --repo "${GITHUB_REPOSITORY}" --delete-branch
git branch -D feat/diagnostics 2>/dev/null || true

9. Создайте рабочий процесс для автономного устранения уязвимостей и автоматического создания запросов на извлечение

Теперь, когда шлюз pull-запросов предотвращает появление новых уязвимостей в базе кода, вы развернете автономное устранение уязвимостей (.github/workflows/codemender-remediate.yml), чтобы активно исправлять существующие уязвимости и открывать готовые к проверке pull-запросы.

Шаг 1. Скачайте файл рабочего процесса устранения неполадок

CodeMender предоставляет два шаблона исправления в зависимости от видимости хранилища:

Общедоступные хранилища и хранилища с открытым исходным кодом (codemender-remediate.yml). Режим ответственного раскрытия информации – ссылки на оповещения SARIF о сканировании кода GitHub без публичного раскрытия необработанных векторов эксплойтов.

Частные и корпоративные репозитории (codemender-remediate-private-repo.yml). Режим доказательств внутреннего аудита – встраивает артефакты проверки (PLAN.md, REPORT.md, exploit.sh) в сворачиваемые разделы запросов на извлечение, исключая их из коммитов Git.

Скачайте в репозиторий рабочий процесс исправления, безопасный для общедоступных репозиториев:

mkdir -p .github/workflows
curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-remediate.yml \
 -o .github/workflows/codemender-remediate.yml

Шаг 2. Запустите рабочий процесс автономного устранения неполадок

Зафиксируйте и отправьте рабочий процесс исправления в основную ветку:

git add .github/workflows/codemender-remediate.yml
git commit -m "ci: add CodeMender autonomous remediation workflow"
git push origin $(git branch --show-current)

В браузере перейдите на вкладку Actions (Действия) хранилища GitHub.

На боковой панели слева в разделе Workflows (Рабочие процессы) выберите CodeMender Autonomous Security Remediation & Auto-PR (Автономное устранение уязвимостей и автоматическое создание запросов на извлечение с помощью CodeMender).

Справа нажмите на зеленый раскрывающийся список Run workflow (Запустить рабочий процесс).

Use workflow from (Использовать рабочий процесс из): убедитесь, что выбрана ветвь по умолчанию (master).

Specific Finding ID or prefix to fix (Идентификатор или префикс конкретной проблемы, которую нужно устранить). Введите восьмизначный префикс для routes/login.ts, записанный на шаге 7 (например, cd47b38a). Если оставить это поле пустым, будет запущено пакетное устранение всех открытых проблем с критическим и высоким уровнем серьезности (это займет около 10–15 минут). Устранение одной проблемы занимает около 45–60 секунд.

Нажмите зеленую кнопку Run workflow (Запустить рабочий процесс) во всплывающем окне и откройте выполняемый запуск.

Запустите рабочий процесс CodeMender Autonomous Security Remediation в раскрывающемся списке Run workflow (Запустить рабочий процесс).

Файл codemender-remediate.yml: автономный синтез исправлений

Пока CodeMender синтезирует исправление в облаке (это занимает около 30–45 секунд), посмотрите, как codemender-remediate.yml (строки 111–184) управляет исправлением в средстве запуска:

Возобновление без сканирования (cm report import). Скачивает артефакт codemender-findings.json из рабочего процесса сканирования и импортирует его в рабочую область (cm report import -f codemender-findings.json). Возврат к cm find . --quick происходит, только если предыдущий артефакт отсутствует.

Headless Patch Synthesis (cm fix): закрепляет project_paths в $GITHUB_WORKSPACE, передает < /dev/null, чтобы предотвратить зависания, и передает --no-reset во время пакетных циклов, чтобы исправления сохранялись в результатах:

# Executed inside the GitHub Actions runner (codemender-remediate.yml)
cm fix "${SPECIFIC_TARGET}" --sandbox=false --yes --bypass-warning < /dev/null

Очистка рабочих коммитов ( строки 155–252). Удаляет .cm_project, .exploit/ и временные файлы с помощью .git/info/exclude, прежде чем peter-evans/create-pull-request@v8 откроет ветку (codemender/auto-remediation-${{ github.run_id }}), фиксируя только изменения рабочего кода:

--- a/routes/login.ts
+++ b/routes/login.ts
@@ -28,8 +28,8 @@ module.exports = function login () {
-    models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: models.User })
+    models.sequelize.query('SELECT * FROM Users WHERE email = :email AND password = :password AND deletedAt IS NULL', {
+      replacements: { email: req.body.email || '', password: security.hash(req.body.password || '') },
+      model: models.User
+    })

Шаг 3. Проверьте новый pull-запрос на GitHub

Перейдите на вкладку Pull requests (Pull-запросы) в репозитории и откройте новый pull-запрос (например, 🛡️ [CodeMender] Fix: SQL Injection in User Authentication Route).

Нажмите Files changed (Измененные файлы) и убедитесь, что изменен только файл routes/login.ts, а все внутренние метаданные среды выполнения исключены.

Проверьте описание запроса на извлечение, которое ссылается непосредственно на оповещение GitHub Code Scanning (SARIF), чтобы получить одобрение от мейнтейнера.

10. Устранение неполадок в пограничных случаях и частных репозиториях

Частные хранилища без GitHub Advanced Security (GHAS)

Общедоступные хранилища GitHub получают бесплатную неограниченную загрузку SARIF-файлов из GitHub Code Scanning. Однако если вы развернете этот рабочий процесс в частном корпоративном репозитории, у которого нет активной лицензии GitHub Advanced Security (GHAS), шаг upload-sarif завершится ошибкой:

HTTP 403: Advanced Security must be enabled for this repository to use code scanning.

Решение: резервный интерактивный HTML-отчет

Встроенный генератор отчетов HTML (cm report -f html) в CodeMender создает отдельную интерактивную панель безопасности с карточками показателей серьезности, фрагментами кода с подсветкой синтаксиса и номерами строк, а также встроенным средством просмотра различий в исправлениях без внешних веб-зависимостей.

Чтобы поддерживать частные репозитории без лицензии GHAS, обновите .github/workflows/codemender-scan.yml, чтобы архивировать артефакт отчета HTML вместо загрузки SARIF:

Создайте отдельный отчет в формате HTML. На этапе Export Security Reports & Publish Job Summary экспортируйте сводку в формате HTML вместе со сводкой в формате Markdown, используя cm report -f html > codemender-audit-report.html.

Архивируйте отчет как артефакт рабочего процесса. Замените шаг Upload SARIF Report to GitHub Code Scanning (github/codeql-action/upload-sarif@v4) на actions/upload-artifact@v4, настроенный для загрузки codemender-audit-report.html (например, под названием артефакта codemender-security-report).

Проверьте локально в любом браузере. Скачайте codemender-security-report.zip со страницы сводки по запуску рабочего процесса GitHub Actions, распакуйте его и откройте codemender-audit-report.html в любом браузере для визуальной сортировки.

Автономное устранение уязвимостей в частных репозиториях со встроенными доказательствами аудита

В частных корпоративных репозиториях командам разработчиков и специалистов по безопасности нужна полная видимость анализа основных причин, проверки концепции эксплойта и плана устранения уязвимостей без необходимости использовать панели инструментов внешних инструментов. Однако добавление скриптов эксплойтов (exploit.sh) или внутренних файлов Markdown (PLAN.md, LOG.md) в ветку репозитория засоряет историю Git и может вызывать ложные срабатывания других сканеров безопасности.

Чтобы устранить эту проблему, разверните специальный рабочий процесс исправления частного хранилища (codemender-remediate-private-repo.yml):

curl -fsSL https://raw.githubusercontent.com/edwardc-gcp/codemender-github-actions/main/.github/workflows/codemender-remediate-private-repo.yml \
 -o .github/workflows/codemender-remediate.yml
git add .github/workflows/codemender-remediate.yml
git commit -m "ci: switch to private repository remediation workflow with embedded audit evidence"
git push origin $(git branch --show-current)

Как работает устранение уязвимостей в частных репозиториях

Динамическая проверка PoC (cm verify). Синтезирует и тестирует работающий эксплойт перед созданием исправления, чтобы подтвердить возможность эксплуатации. Если проверка помечает неэксплуатируемую уязвимость как DISMISSED, cm fix автоматически пропускается.

Сворачиваемые блоки аудита pull-запросов. Извлекает REPORT.md, PLAN.md и exploit.sh в /tmp/codemender-evidence/ и форматирует их непосредственно в описании pull-запроса внутри сворачиваемых блоков <details open> для проверки рецензентом в один клик.

Архивирование артефактов. Архивация всей папки с доказательствами с помощью actions/upload-artifact@v4.

Pristine Git Commits. Удаляет все метаданные среды выполнения и каталоги .exploit, чтобы коммит Git в pull-запросе содержал только изменения в рабочем коде.

Контрольный список для устранения неполадок с Workload Identity Federation (WIF)

По умолчанию google-github-actions/auth@v2 записывает локальный файл конфигурации федеративных учетных данных во время настройки, а фактический обмен токенами OAuth 2.0 происходит при запуске cm health --strict или cm find. Чтобы диагностировать ошибки аутентификации HTTP 400 или HTTP 403, воспользуйтесь контрольным списком ниже.

Признак ошибки

Распространенная основная причина

Проверка и исправление

HTTP 403 (iam.serviceAccounts.getAccessToken denied)

Отсутствует привязка roles/iam.workloadIdentityUser в сервисном аккаунте, указан неверный секретный ключ GCP_SERVICE_ACCOUNT или не включен iamcredentials.googleapis.com.

Убедитесь, что GCP_SERVICE_ACCOUNT совпадает с codemender-ci-runner@.iam.gserviceaccount.com, и запустите проверку правил IAM ниже, чтобы подтвердить привязку principalSet.

HTTP 400 (unauthorized_client или отклоненное условие атрибута).

Название (или регистр) хранилища OIDC –attribute-condition не совпадает с хранилищем GitHub, запускающим рабочий процесс, или поставщик WIF отключен.

Повторно выполните шаг 4 (шаги 1 и 6), убедившись, что регистр ${GITHUB_REPOSITORY} точно соответствует регистру owner/repo на GitHub и применяется –no-disabled.

HTTP 400 (invalid_grant при обмене токенами)

Неверный формат –issuer-uri или отсутствует сопоставление attribute.repository=assertion.repository у поставщика OIDC.

Убедитесь, что для параметра –issuer-uri задано значение https://token.actions.githubusercontent.com (без косой черты в конце).

Временная ошибка HTTP 403 сразу после настройки

Распространение глобальных настроек IAM и Workload Identity Federation для новых привязок может занять от 1 до 5 минут.

Подождите 1–2 минуты и нажмите Re-run failed jobs (Повторно запустить невыполненные задания) в GitHub Actions.

Чтобы проверить привязку Workload Identity в сервисном аккаунте CI/CD в Cloud Shell, выполните следующую команду:

gcloud iam service-accounts get-iam-policy "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" \
 --flatten="bindings[].members" \
 --filter="bindings.role=roles/iam.workloadIdentityUser"

Убедитесь, что в выходных данных roles/iam.workloadIdentityUser привязано к principalSet://iam.googleapis.com/<POOL_ID>/attribute.repository/<GITHUB_USER>/<GITHUB_REPO>:

---
bindings:
 members: principalSet://iam.googleapis.com/.../attribute.repository/<OWNER>/<REPO>
 role: roles/iam.workloadIdentityUser

Устранение неполадок с предварительной проверкой CI/CD и кодом выхода CLI

Команды CodeMender (cm health --strict, cm find, cm verify и cm fix) возвращают детерминированные коды выхода, поэтому конвейеры CI/CD могут сразу отличить результаты проверки безопасности от ошибок настройки или сервиса:

Код выхода

Категория

Распространенные основные причины и способы устранения

0

Выполнено

Проверки работоспособности пройдены или сканирование завершено без обнаружения блокирующих проблем.

1

Фурнитура/Общее

Обнаружено –fail-on уязвимостей, блокирующих CRITICAL или HIGH в запросе на извлечение (ожидаемый сбой шлюза слияния).

10

credentials

Не удалось обменять токен WIF OAuth/ADC (400/401). Проверьте GCP_WORKLOAD_IDENTITY_PROVIDER, GCP_SERVICE_ACCOUNT и привязку roles/iam.workloadIdentityUser выше.

20

config

Недопустимый синтаксис .codemender/config.yaml или ~/.codemender/config.yaml.

30

reachability

Исполнитель не может подключиться к aiplatform.googleapis.com (DNS, прокси, сбой сервиса или Управление зонами безопасности VPC).

40

authorization

В целевом проекте у сервисного аккаунта нет роли roles/aiplatform.user или отключен API cloudresourcemanager.googleapis.com/aiplatform.googleapis.com.

50

timeout

Предварительная проверка cm health заняла больше 30 секунд.

60

capacity

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

Информацию о других ошибках выполнения, например о разрешении базовой ветви Git diff (fetch-depth: 0), задержках распространения ресурсов или разрешениях на создание pull-запросов GitHub Actions, можно найти в официальном руководстве по устранению неполадок CodeMender CI/CD.

11. Очистка ресурсов

Чтобы предотвратить дальнейшее потребление ресурсов или очистить тестовые конфигурации в средах Google Cloud и GitHub, выполните следующие действия по очистке.

Шаг 1. Удалите секреты хранилища GitHub и отключите рабочие процессы с помощью gh CLI

Используйте GitHub CLI (gh), чтобы удалить секреты Actions из хранилища и отключить рабочие процессы CodeMender:

# Delete the repository Actions secrets
gh secret delete GCP_WORKLOAD_IDENTITY_PROVIDER --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
gh secret delete GCP_SERVICE_ACCOUNT --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true

# Disable the CodeMender workflows to prevent unwanted automatic triggers
gh workflow disable codemender-scan.yml --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true
gh workflow disable codemender-remediate.yml --repo "${GITHUB_REPOSITORY}" 2>/dev/null || true

Шаг 2. Отключите или удалите ресурсы Workload Identity Federation в Google Cloud

Пулы Workload Identity, поставщики и сервисные аккаунты не требуют затрат, когда не обмениваются токенами. Выберите режим очистки, который соответствует вашему рабочему процессу:

Вариант А. Приостановка доступа (рекомендуется, если вы планируете повторно запустить проект). Немедленно отключает обмен токенами OIDC, не запуская 30-дневное хранение удаленных данных Google Cloud IAM или задержки распространения uniqueId сервисного аккаунта.

gcloud iam workload-identity-pools providers update-oidc "${WORKLOAD_IDENTITY_PROVIDER}" \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --disabled \
 --project="${PROJECT_ID}"

Вариант Б. Полное удаление. Удаление поставщика федеративной идентификации рабочей нагрузки, пула (сохраняется в состоянии DELETED в течение 30 дней) и выделенного сервисного аккаунта.

# Delete Workload Identity Provider
gcloud iam workload-identity-pools providers delete "${WORKLOAD_IDENTITY_PROVIDER}" \
 --workload-identity-pool="${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --project="${PROJECT_ID}" \
 --quiet

# Delete Workload Identity Pool
gcloud iam workload-identity-pools delete "${WORKLOAD_IDENTITY_POOL}" \
 --location="global" \
 --project="${PROJECT_ID}" \
 --quiet

# Delete CI/CD Service Account
gcloud iam service-accounts delete "${SERVICE_ACCOUNT_EMAIL}" \
 --project="${PROJECT_ID}" \
 --quiet

12. Поздравляю!

Поздравляем! Вы завершили практическую работу Как защитить конвейер CI/CD с помощью CodeMender.

Вы успешно спроектировали, создали и автоматизировали конвейер DevSecOps с нулевым доверием производственного уровня, используя федерацию Workload Identity Google Cloud, CodeMender и GitHub Actions.

Что вы узнали

Аутентификация без ключей с нулевым доверием. Мы отказались от использования небезопасных долгосрочных JSON-ключей сервисных аккаунтов, связав временные токены OIDC GitHub с Google Cloud IAM через Workload Identity Federation (WIF).

Дифференциальное AST-сканирование PR и шумоподавление устаревшего шума. Ограниченное непрерывное сканирование измененных файлов и зависимостей (--diff="origin/$BASE_REF"), изолирующее устаревший технический долг ([LEGACY / UNTOUCHED]), чтобы циклы обратной связи с разработчиками не превышали 15 секунд.

Многоформатные отчеты и сводки по заданиям. Мы объединили OASIS SARIF версии 2.1.0 для централизованного сканирования кода GitHub с нативным Markdown (cm report -f md >> $GITHUB_STEP_SUMMARY), чтобы руководители могли мгновенно получать информацию прямо на страницах выполнения рабочих процессов непрерывной интеграции.

Автономное устранение уязвимостей с участием человека в контуре. Мы перешли от пассивных уведомлений к активным конвейерам устранения уязвимостей, которые автономно синтезируют предлагаемые исправления кода, проверяют их с помощью наборов регрессионных тестов и открывают pull-запросы на проверку с артефактами аудита для утверждения инженером.

Автоматизированные строгие проверки качества. Внедрена строгая защита ветвей и контроль слияния (--fail-on), чтобы опасные уязвимости не попадали в рабочую среду.

Передача состояния на основе артефактов и изоляция рабочей области. Результаты сканирования передаются между заданиями непрерывной интеграции с помощью cm report import, а .git/info/exclude используется для сохранения исходной истории Git и предотвращения утечки учетных данных.

Изменение мышления разработчиков

Традиционная практика DevSecOps

Автономный конвейер непрерывной интеграции и непрерывной поставки CodeMender

Пассивный сброс оповещений. Сканеры выводят необработанные журналы терминала или статические списки ошибок, полностью перекладывая бремя сортировки на разработчиков.

Активный помощник в разработке. Синтезирует проверенные исправления кода и открывает готовые к слиянию запросы на включение изменений, которые инженеры могут одобрить.

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

Двухуровневая проверка эксплойтов. Динамическое создание тестов в изолированной среде (cm verify) подтверждает наличие уязвимости, исключая ложные срабатывания.

Рискованное хранение секретов. JSON-ключи сервисных аккаунтов с длительным сроком действия, хранящиеся в секретах CI, могут быть случайно раскрыты или утеряны.

Федеративная идентификация рабочих нагрузок с нулевым доверием. Аутентификация без ключа с помощью временных токенов OIDC, которыми можно обмениваться с Google Cloud STS по запросу.

Монолитные повторные сканирования. Каждая фиксация запускает полный аудит репозитория, задерживая рабочие процессы непрерывной интеграции и тратя дорогостоящие токены.

Маршрутизация AST с учетом событий. Pull-запросы выполняют 15-секундные дифференциальные сканирования AST (–diff), а cron-задачи – глубокие аудиты.

Загрязнение истории репозитория. Временные скрипты эксплойтов и журналы атак, зафиксированные непосредственно в ветках репозитория.

Чистота рабочей среды. Доказательства атаки встраиваются в описания запросов на перенос и артефакты рабочих процессов, не затрагивая фиксации кода.

Дальнейшие действия

🚀 Продолжайте изучать CodeMender

Часть 1. Защита приложения с помощью CodeMender. Научитесь автономно обнаруживать уязвимости в хранилище, проверять эксплойты PoC и синтезировать локальные исправления.

Shift Left Locally & Serverless Cloud Native CI/CD. Ознакомьтесь с примерами реализации в официальном руководстве по CI/CD для Google Cloud Build (cloudbuild.yaml) и локальных хуков Git pre-commit (cm find . --diff --staged).

📖 Документация и ресурсы

Официальное руководство по интеграции CodeMender с CI/CD в Google Cloud

Официальная документация по Google Cloud CodeMender

Репозиторий шаблонов CodeMender GitHub Actions Starter

Документация по Workload Identity Federation в Google Cloud

💡 Примените к своим хранилищам

Создайте форк начального рабочего процесса и защитите репозитории Python, Go, Java, Rust и Node.js вашей организации с помощью CodeMender.