GHSA-x4q3-gcj3-m6cf: Critical severity go/gitea.com/gitea/runner vulnerability
Summary actrunner appends workflow-controlled jobs.<job>.container.options directly to the Docker HostConfig for the job container. When runner privileged mode is disabled, only Privileged is forced false. Host namespace flags, capability expansion, and security profile overrides from workflow YAML are preserved in the final HostConfig. A workflow author can enter host PID/IPC namespaces and execute commands on the runner host as root.
Details Source-to-sink path in actrunner:
- ContainerSpec.Options accepts workflow YAML container.options - RunContext.options() appends workflow options to runner-level container options - Job container is created with Privileged: rc.Config.Privileged but also with Options: rc.options(ctx) - mergeContainerConfigs() parses Docker CLI-style options into HostConfig - When privileged mode is disabled, only copts.privileged is forced false - sanitizeConfig() only filters Binds and Mounts - Preserved dangerous HostConfig fields:
text Privileged=false PidMode=host IpcMode=host CapAdd=["ALL"] SecurityOpt=["seccomp=unconfined","apparmor=unconfined"]
Attacker workflow YAML: yaml jobs: breakout: runs-on: ubuntu-latest container: image: ubuntu:22.04 options: >- --pid=host --ipc=host --cap-add=ALL --security-opt seccomp=unconfined --security-opt apparmor=unconfined steps: - name: host namespace marker run: | nsenter -t 1 -m -u -i -n -p -- sh -c "id > /tmp/marker"
Impact An attacker who can submit a workflow to a repository using a shared Docker-backed actrunner can:
- Enter host PID, IPC, and mount namespaces - Execute arbitrary commands as root on the runner host - Access runner host secrets, deployment credentials, and environment variables - Pivot to adjacent jobs running on the same runner - Access internal build infrastructure reachable from the runner host
Critical severity for shared runners where untrusted users can trigger workflows. High severity for single-tenant runners with privileged mode explicitly disabled as a security control.
Fix Direction Treat container.options as untrusted input. Reject or strip when privileged mode is disabled:
- Host namespaces: --pid=host, --ipc=host, --uts=host, --network=host - Capability expansion: --cap-add ALL, --cap-add SYSADMIN - Security overrides: --security-opt seccomp=unconfined, --security-opt apparmor=unconfined - Device access: --device, --device-cgroup-rule - Volume inheritance: --volumes-from - Runtime controls: --runtime, --cgroup-parent
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/gitea.com/gitea/runnerto a version that resolves this vulnerability.Fixed in 1.0.9-0.20260731160927-34bfa1915022 - Configuration
Treat workflow-controlled jobs.<job>.container.options as untrusted input and reject or strip options including --pid=host, --ipc=host, --uts=host, --network=host, --cap-add=ALL, --cap-add=SYS_ADMIN, --device, --device-cgroup-rule, --runtime, --cgroup-parent, --security-opt seccomp=unconfined, --security-opt apparmor=unconfined, and --volumes-from before converting them into Docker HostConfig.
Docker-backed act_runner container.options = reject or strip host namespace, capability, device, runtime, cgroup-parent, security-opt, and volumes-from options
Event History
Frequently Asked Questions
Does disabling privileged mode on the runner prevent exploitation?
No. With privileged mode disabled, the runner forces only Privileged=false; workflow-provided host namespace settings, added capabilities, and security profile overrides can still be preserved in the Docker HostConfig.
Who can realistically exploit this issue?
A workflow author who can control jobs.<job>.container.options can exploit it. The supplied options can place the job container in the host PID and IPC namespaces and enable host-level command execution as root.
What should be checked to identify exposure?
Review workflow YAML for container.options and inspect resulting job-container HostConfig values. Indicators include PidMode=host, IpcMode=host, CapAdd containing ALL, and SecurityOpt values such as seccomp=unconfined or apparmor=unconfined.
What can be done if patching cannot happen immediately?
Limit workflow authoring and modification permissions to trusted users, because exploitation requires control of workflow container options. Treat runners that execute untrusted or contributor-controlled workflows as exposed.