---
season: 3
season_name: "Season 3 — October 2026 (Autumn / Halloween Edition)"
day: 25
title: "CodeMender: Fix Vulnerable Code Before It Merges"
summary: "Scan every pull request with CodeMender, prove each finding with a sandboxed exploit, and commit a reviewed patch before the code merges."
tags: ["Phase 5: CodeMender", "Security", "CI/CD", "Vulnerability Remediation"]
canonical_url: "https://adventofagents.com/2026/10/25"
markdown_url: "https://adventofagents.com/2026/10/25.md"
video_url: "https://www.youtube.com/embed/LerewxBM0rM"
primary_video:
  title: "Day 25: Automated Vulnerability Remediation with CodeMender"
  creator_name: "Manish Gaur"
  duration: "12:55"
  video_url: "https://www.youtube.com/embed/LerewxBM0rM"
---

# 🩹 Day 25: CodeMender: Fix Vulnerable Code Before It Merges

> **Season 3 — October 2026 (Autumn / Halloween Edition)** · [Interactive Web View](https://adventofagents.com/2026/10/25?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day25) · [Raw Markdown](https://adventofagents.com/2026/10/25.md?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day25)

**Summary:** Scan every pull request with CodeMender, prove each finding with a sandboxed exploit, and commit a reviewed patch before the code merges.

**Day 25 of Google's Advent of Agents — Season 3**

*Disclaimer: CodeMender is currently in Public Preview with gated access. To gain access, customers must submit an access form and be allowlisted by the CodeMender Product Management team.*

Day 24 caught an agent acting off-script at runtime. Today's question is how to fix the code that made it possible. Agent tools are ordinary code that a model calls with arguments it chose, so an injection flaw or an over-broad tool like Day 24's `fetch_records` turns a single prompt injection into a breach. Scanners that file findings in a separate dashboard leave the fix for later, and later often means after the merge.

**How It Works**

**CodeMender** works inside the pull request. A GitHub Actions workflow authenticates to Google Cloud with Workload Identity Federation, so no service account keys live in GitHub, and sends every PR event to CodeMender on Cloud Run. CodeMender scans the cumulative diff, posts one sticky comment listing each finding, and sets the `security/codemender-gate` status check, which fails while Critical findings are open. Developers drive the rest with slash commands on the PR.

![CodeMender Architecture Flow](/s03/s3-day25-cm-flow.png)

A draft pull request triggers CodeMender on Cloud Run through GitHub Actions; CodeMender scans, verifies the finding with a sandboxed exploit, and stages a fix that a reviewer approves before the security gate allows the merge.

- **Verify before you trust**: `/verify` generates an exploit and runs it in an isolated sandbox, so a finding is marked verified only when it is actually exploitable.
- **Fix with a human in the loop**: `/fix` stages a patch as a unified diff in the PR comment, and nothing is committed until a reviewer replies `/approve`. The gate then turns green.
- **Audit every decision**: Findings, exploit results, and approved patches are recorded in BigQuery, so you can show what was found, proven, and fixed.
- **Run the PoC yourself**: The [CodeMender GitOps Starter Kit](https://github.com/GCP-Architecture-Guides/codemender-gitops-starter-kit?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day25) deploys this pipeline to a sandbox project with one script and ships vulnerable samples in Python, Node.js, Go, Java, and Terraform. It is PoC code, so use a dev environment.

**Resources:**

- [CodeMender GitOps Starter Kit](https://g.dev/cloud/adventofagents-season3-day25-demo)
- [CodeMender PoC Guide](https://g.dev/cloud/adventofagents-season3-day25-poc-guide)
- [Introducing CodeMender](https://g.dev/cloud/adventofagents-season3-blog-introducing-codemender)
- [Workload Identity Federation for CI/CD](https://g.dev/cloud/adventofagents-season3-docs-wif-deployment-pipelines)

## Code & Commands

### 1. Deploy the Starter Kit (one-time setup)

```bash
export CLOUDSDK_METRICS_ENVIRONMENT="advent-of-agents-s3-day25"

# One-time setup. You need a sandbox Google Cloud project with billing, gcloud,
# a test GitHub repo, and a fine-grained PAT on that repo with Read & Write on
# Contents, Pull requests, Commit statuses, Issues, and Workflows.
git clone https://github.com/GCP-Architecture-Guides/codemender-gitops-starter-kit
cd codemender-gitops-starter-kit

# Provide your GCP project, new repo for your PR workflow and your Git repo PAT token for deployment
gcloud auth login && gcloud auth application-default login
export PROJECT_ID="your-sandbox-project"
export TARGET_REPO="your-org/codemender-poc-test"
printf "GitHub PAT: " && read -rs GITHUB_PAT && echo   # keeps the token out of shell history

# Deploys the CodeMender pipeline to Cloud Run with keyless GitHub auth (Workload
# Identity Federation), then pushes .github/workflows/codemender.yml to TARGET_REPO.
./deploy.sh \
  --project "$PROJECT_ID" \
  --region us-central1 \
  --repo "$TARGET_REPO" \
  --token "$GITHUB_PAT" \
  --multi-service

# Optional: in GitHub Settings > Branches, require the "security/codemender-gate" check on main.
```

### 2. Open a PR, Then Verify, Fix, and Approve

```bash
# The kata. Run in the same shell as Tab 1.
git clone "https://github.com/$TARGET_REPO.git" && cd "${TARGET_REPO#*/}"
git checkout -b test/codemender-scan

# Add a deliberately vulnerable Flask app (SQL injection, command injection, XSS, IDOR).
curl -sLo app.py https://raw.githubusercontent.com/GCP-Architecture-Guides/codemender-gitops-starter-kit/main/samples/vulnerable_app.py
git add app.py && git commit -m "feat: add login endpoint"
git push -u origin test/codemender-scan

# Then, in GitHub:
# 1. Open a draft pull request from test/codemender-scan.
# 2. CodeMender posts one sticky comment listing each finding (CWE, file, line, severity),
#    and the security/codemender-gate check fails on Critical findings.
# 3. Reply on the PR, letting the comment update between steps:
#    /verify all   runs a generated exploit in a sandbox to prove the finding is real
#    /fix all      stages a patch in the comment as a unified diff
#    /approve      commits the patch to your branch; the gate turns green
# Findings, exploit results, and approved patches land in BigQuery (codemender_analytics) for audit.
# Disclaimer: CodeMender is currently in Public Preview with gated access. To gain access, customers must submit an access form and be allowlisted by the CodeMender Product Management team.
```

### 3. The PR Trigger deploy.sh Adds to Your Repo

```yaml
# deploy.sh generates this file with your project values and pushes it to TARGET_REPO.
name: CodeMender Agent Integration

on:
  pull_request:
    types: [opened, reopened, synchronize, ready_for_review]
  issue_comment:              # slash commands on the PR drive remediation
    types: [created]

permissions:
  id-token: write             # GitHub OIDC token; no service account keys stored in GitHub
  contents: read

jobs:
  codemender-security-gate:
    if: >
      github.event_name == 'pull_request' ||
      (github.event_name == 'issue_comment' && github.event.issue.pull_request &&
       (startsWith(github.event.comment.body, '/verify') ||
        startsWith(github.event.comment.body, '/fix') ||
        startsWith(github.event.comment.body, '/approve') ||
        startsWith(github.event.comment.body, '/dismiss')))
    runs-on: ubuntu-latest
    steps:
      - name: Authenticate to Google Cloud (WIF)
        id: auth
        uses: google-github-actions/auth@v2
        with:
          token_format: 'id_token'
          workload_identity_provider: 'projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
          service_account: 'codemender-trigger@<PROJECT_ID>.iam.gserviceaccount.com'
          id_token_audience: 'https://codemender-backend-<PROJECT_NUMBER>.<REGION>.run.app'
          id_token_include_email: true

      - name: Dispatch Scan / Slash Command to CodeMender
        run: |
          curl -sf -X POST "https://codemender-backend-<PROJECT_NUMBER>.<REGION>.run.app/github-webhook" \
            -H "Authorization: Bearer ${{ steps.auth.outputs.id_token }}" \
            -H "X-CodeMender-Auth: WIF" \
            -H "Content-Type: application/json" \
            -H "X-GitHub-Event: ${{ github.event_name }}" \
            -d @$GITHUB_EVENT_PATH
```

## Resources & Links

- **[CodeMender GitOps Starter Kit](https://g.dev/cloud/adventofagents-season3-day25-demo)** — Deploy the PR pipeline to a sandbox project and run the PoC end to end.
- **[CodeMender PoC Guide](https://g.dev/cloud/adventofagents-season3-day25-poc-guide)** — Step-by-step test scenarios with vulnerable samples.
- **[Introducing CodeMender](https://g.dev/cloud/adventofagents-season3-blog-introducing-codemender)** — How CodeMender reasons about code and validates its fixes to avoid regressions.
- **[Workload Identity Federation for CI/CD](https://g.dev/cloud/adventofagents-season3-docs-wif-deployment-pipelines)** — The keyless GitHub-to-Google Cloud authentication the PR workflow uses.
