Fixes CVE-2026-111497 (Brotli decoder out-of-bounds write, CISA KEV, due 2026-11-10) in the runner toolchain image, used by forgejo-runner and zegit-runner in flux-config, and as the base of markus/gitea-runner. Markus approved this on 2026-11-07.
The forgejo/runner:12.11.1 base ships brotli-libs 1.2.0-r0.
apk add never upgrades a package the base already has, so the long apk add list did not fix it.
This PR adds an explicit apk upgrade brotli-libs (→ 1.2.1-r0, same Alpine branch) and a build gate: the build fails if brotli-libs is still older than 1.2.1-r0. A base bump therefore cannot quietly bring the vulnerable version back.
Reachability is low: the runners are mesh-only, and git-remote-http/curl link brotli via libcurl when fetching from forges. But the runners execute every zegit CI job, so they get patched too.
Tested
A local docker buildx build for linux/amd64 and linux/arm64 (cache only) passes on both arches with Upgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0) and brotli-libs 1.2.1-r0. The rest of the Dockerfile is unchanged.
After merge
Publish 12.11.1-ci9: dispatch "build image (Gitea)" with tag=12.11.1-ci9. It builds, asserts the toolchain, and cosign-signs with the runner-image key. Tags are immutable.
I open the flux-config PR that pins forgejo-runner and zegit-runner to 12.11.1-ci9@<digest>, plus the markus/gitea-runner base bump. Then I run a test job on the new image before calling it done.
zegit's CI runs on these runners, so before the pin is ready I'll check that a real zegit CI job passes on the new image.
## What
Fixes **CVE-2026-111497** (Brotli decoder out-of-bounds write, CISA KEV, due 2026-11-10) in the runner toolchain image, used by `forgejo-runner` and `zegit-runner` in flux-config, and as the base of `markus/gitea-runner`. Markus approved this on 2026-11-07.
- The `forgejo/runner:12.11.1` base ships `brotli-libs 1.2.0-r0`.
- `apk add` never upgrades a package the base already has, so the long `apk add` list did not fix it.
- This PR adds an explicit `apk upgrade brotli-libs` (→ 1.2.1-r0, same Alpine branch) and a **build gate**: the build fails if `brotli-libs` is still older than 1.2.1-r0. A base bump therefore cannot quietly bring the vulnerable version back.
Reachability is low: the runners are mesh-only, and `git-remote-http`/`curl` link brotli via libcurl when fetching from forges. But the runners execute every zegit CI job, so they get patched too.
## Tested
A local `docker buildx` build for **linux/amd64 and linux/arm64** (cache only) passes on both arches with `Upgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0)` and `brotli-libs 1.2.1-r0`. The rest of the Dockerfile is unchanged.
## After merge
1. Publish **`12.11.1-ci9`**: dispatch "build image (Gitea)" with `tag=12.11.1-ci9`. It builds, asserts the toolchain, and cosign-signs with the runner-image key. Tags are immutable.
2. I open the flux-config PR that pins `forgejo-runner` and `zegit-runner` to `12.11.1-ci9@<digest>`, plus the markus/gitea-runner base bump. Then I run a test job on the new image before calling it done.
zegit's CI runs on these runners, so before the pin is ready I'll check that a real zegit CI job passes on the new image.
Agent-Session: 542e8b23-4b8c-5dfa-a986-6b3d431a3804
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The forgejo/runner:12.11.1 base ships brotli-libs 1.2.0-r0, and `apk add`
never upgrades a package the base already has. Upgrade it explicitly
(-> 1.2.1-r0) and fail the build if it is still older, so a base bump
cannot bring the vulnerable version back. Markus approved 2026-11-07.
Tested locally: builds for linux/amd64 and linux/arm64,
"Upgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0)", gate passes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Markus chose (2026-11-07 ~10:21Z) to merge this without waiting for the agent-peer verdict, because of the CISA KEV due date (2026-11-10). The review request stays open (zegit-zoo/zegit-forgejo-runner#1 on GitHub), and anything Jonas's agent raises gets a follow-up PR.
The evidence at head 09e32c118603:
This repo has no PR CI. build-image-gitea.yml runs only on push to master (build-only validation) and on dispatch (publish). An earlier status of mine called this "green"; that was wrong.
A local docker buildx build --platform linux/amd64,linux/arm64 passes. Both arches log Upgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0), then brotli-libs 1.2.1-r0, and the new gate passes. No other package is upgraded.
After merge, the master build re-validates it on both arches through the in-cluster buildkitd. Before any pin, 12.11.1-ci9 is published by dispatch, cosign-signed and verified.
Markus chose (2026-11-07 ~10:21Z) to merge this **without waiting for the agent-peer verdict**, because of the CISA KEV due date (2026-11-10). The review request stays open (zegit-zoo/zegit-forgejo-runner#1 on GitHub), and anything Jonas's agent raises gets a follow-up PR.
The evidence at head `09e32c118603`:
- This repo has **no PR CI**. `build-image-gitea.yml` runs only on push to master (build-only validation) and on dispatch (publish). An earlier status of mine called this "green"; that was wrong.
- A local `docker buildx build --platform linux/amd64,linux/arm64` passes. Both arches log `Upgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0)`, then `brotli-libs 1.2.1-r0`, and the new gate passes. No other package is upgraded.
- After merge, the master build re-validates it on both arches through the in-cluster buildkitd. Before any pin, `12.11.1-ci9` is published by dispatch, cosign-signed and verified.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
agent
marked the pull request as ready for review 2026-11-07 10:21:34 +00:00
markus
merged commit 5a64cddb92 into master2026-11-07 10:22:25 +00:00
markus
deleted branch claude/fix/brotli-kev2026-11-07 10:22:26 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Fixes CVE-2026-111497 (Brotli decoder out-of-bounds write, CISA KEV, due 2026-11-10) in the runner toolchain image, used by
forgejo-runnerandzegit-runnerin flux-config, and as the base ofmarkus/gitea-runner. Markus approved this on 2026-11-07.forgejo/runner:12.11.1base shipsbrotli-libs 1.2.0-r0.apk addnever upgrades a package the base already has, so the longapk addlist did not fix it.apk upgrade brotli-libs(→ 1.2.1-r0, same Alpine branch) and a build gate: the build fails ifbrotli-libsis still older than 1.2.1-r0. A base bump therefore cannot quietly bring the vulnerable version back.Reachability is low: the runners are mesh-only, and
git-remote-http/curllink brotli via libcurl when fetching from forges. But the runners execute every zegit CI job, so they get patched too.Tested
A local
docker buildxbuild for linux/amd64 and linux/arm64 (cache only) passes on both arches withUpgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0)andbrotli-libs 1.2.1-r0. The rest of the Dockerfile is unchanged.After merge
12.11.1-ci9: dispatch "build image (Gitea)" withtag=12.11.1-ci9. It builds, asserts the toolchain, and cosign-signs with the runner-image key. Tags are immutable.forgejo-runnerandzegit-runnerto12.11.1-ci9@<digest>, plus the markus/gitea-runner base bump. Then I run a test job on the new image before calling it done.zegit's CI runs on these runners, so before the pin is ready I'll check that a real zegit CI job passes on the new image.
Agent-Session: 542e8b23-4b8c-5dfa-a986-6b3d431a3804
🤖 Generated with Claude Code
Markus chose (2026-11-07 ~10:21Z) to merge this without waiting for the agent-peer verdict, because of the CISA KEV due date (2026-11-10). The review request stays open (zegit-zoo/zegit-forgejo-runner#1 on GitHub), and anything Jonas's agent raises gets a follow-up PR.
The evidence at head
09e32c118603:build-image-gitea.ymlruns only on push to master (build-only validation) and on dispatch (publish). An earlier status of mine called this "green"; that was wrong.docker buildx build --platform linux/amd64,linux/arm64passes. Both arches logUpgrading brotli-libs (1.2.0-r0 -> 1.2.1-r0), thenbrotli-libs 1.2.1-r0, and the new gate passes. No other package is upgraded.12.11.1-ci9is published by dispatch, cosign-signed and verified.🤖 Generated with Claude Code