CVE-2026-61549 — woodpecker
Fix: woodpecker-ci/woodpecker@5df9d52CVE-2026-61549 is a Improper Privilege Management vulnerability in go.woodpecker-ci.org/woodpecker/v3. A fix is available for go.woodpecker-ci.org/woodpecker/v3 — see the affected versions and patch details below.
Woodpecker: Privilege escalation via unrestricted serviceAccountName in the Kubernetes backend
Exploitation Status
No confirmed exploitation observed yet
- A successful exploit gives an attacker total control of the affected component, not partial access.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-61549.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
go.woodpecker-ci.org/woodpecker/v3🐹github.com/woodpecker-ci/woodpecker🐹go.woodpecker-ci.org/woodpecker/v2Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Impact
A privilege escalation vulnerability affects Woodpecker instances using the Kubernetes backend.
The pipeline option backend_options.kubernetes.serviceAccountName was passed directly to the pod spec without any admin gating.
Who is impacted: any operator running the Kubernetes backend. Any user with Push permission on a connected repository can run pipeline pods under an arbitrary ServiceAccount in the pipeline namespace, gaining that account's RBAC permissions. If a privileged ServiceAccount is reachable in that namespace, this can lead to secret exfiltration (database credentials, API keys, TLS certs) and full cluster takeover.
Patches
https://github.com/woodpecker-ci/woodpecker/pull/6792
Workarounds
Operators who cannot upgrade immediately can mitigate by any of:
- Restrict Push access on repositories connected to the Kubernetes-backed instance to trusted users only.
- Harden the pipeline namespace: ensure no privileged ServiceAccount exists or is bound in
the namespace where pipeline pods run; keep the
defaultServiceAccount minimally privileged. - Disable ServiceAccount token automounting for ServiceAccounts that should not be used by pipelines.
- Enforce an admission policy (e.g. OPA/Gatekeeper, Kyverno, or a ValidatingAdmissionPolicy)
that rejects pipeline pods setting an unexpected
serviceAccountName. - Use a dedicated, isolated namespace per org/instance with no sensitive RBAC bindings.
Resources
- Vulnerable option introduced in commit
609ba481b5e912f59aaae8ca7bc22b44523c5e37 - Affected versions:
v1.0.0throughv3.15.0 - Source:
pipeline/backend/kubernetes/backend_options.go(fieldServiceAccountName),pipeline/backend/kubernetes/pod.go(assigned to pod spec with no gating)
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | go.woodpecker-ci.org/woodpecker/v3 | all versions | 3.16.0go get go.woodpecker-ci.org/woodpecker/v3@v3.16.0 |
| 🐹Go | github.com/woodpecker-ci/woodpecker | ≥ 1.0.0 | No fix |
| 🐹Go | go.woodpecker-ci.org/woodpecker/v2 | all versions | No fix |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for go.woodpecker-ci.org/woodpecker/v3, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update go.woodpecker-ci.org/woodpecker/v3 to 3.16.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-61549 is resolved across your whole dependency graph.
Workarounds
Close the privilege gap rather than the entry point: audit which accounts, roles and service identities can reach the affected operation, drop the component to the least privilege it actually needs, and review file and directory permissions created by earlier installs — a default left in place is what makes this reachable.
Frequently Asked Questions
Is CVE-2026-61549 in your dependencies?
Find it across Go, including transitive dependencies.