From 83b63250a312f39908569f388a8497dd2a5c92ed Mon Sep 17 00:00:00 2001 From: bircni Date: Wed, 7 Oct 2026 19:04:04 +0000 Subject: [PATCH] fix: strip log-driver and OOM options when privileged is off (#1283) When privileged mode is disabled, reset `--log-driver`, `--log-opt`, `--oom-score-adj` and `--oom-kill-disable` from workflow `container.options`. Log drivers run in the host daemon, so a workflow could make it connect to any address, and `--oom-score-adj -1000` exempts a job from the host OOM killer. Breaking: on unprivileged runners, workflows can no longer set these options, e.g. `--log-driver none` or `--log-opt max-size=10m`. They are dropped with a warning and the job still runs. Runner-level `container.options` and privileged runners are unaffected. Fixes: https://github.com/go-gitea/gitea/security/advisories/GHSA-cgx2-cw7h-xgcx Fixes: https://github.com/go-gitea/gitea/security/advisories/GHSA-c988-q5xx-2cff Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: silverwind Reviewed-on: https://gitea.com/gitea/runner/pulls/1283 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> --- act/container/docker_run.go | 4 ++++ act/container/docker_run_test.go | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/act/container/docker_run.go b/act/container/docker_run.go index 04ea67dd..50997cf9 100644 --- a/act/container/docker_run.go +++ b/act/container/docker_run.go @@ -1117,6 +1117,10 @@ func sanitizeOptionsHostConfig(logger logrus.FieldLogger, hostConfig, trusted *c // systempaths=unconfined lands in these two rather than in SecurityOpt resetOption(logger, "--security-opt", &hostConfig.MaskedPaths, trusted.MaskedPaths) resetOption(logger, "--security-opt", &hostConfig.ReadonlyPaths, trusted.ReadonlyPaths) + resetOption(logger, "--log-driver", &hostConfig.LogConfig.Type, trusted.LogConfig.Type) // drivers run in the daemon, egressing from its network + resetOption(logger, "--log-opt", &hostConfig.LogConfig.Config, trusted.LogConfig.Config) + resetOption(logger, "--oom-score-adj", &hostConfig.OomScoreAdj, trusted.OomScoreAdj) // -1000 exempts it from the host OOM killer + resetOption(logger, "--oom-kill-disable", &hostConfig.OomKillDisable, trusted.OomKillDisable) // a driver mounts what it likes, e.g. local with device= binds any host path, which // valid_volumes never gets to see diff --git a/act/container/docker_run_test.go b/act/container/docker_run_test.go index 70c40ed0..249141d5 100644 --- a/act/container/docker_run_test.go +++ b/act/container/docker_run_test.go @@ -666,6 +666,9 @@ func TestSanitizeOptionsHostConfig(t *testing.T) { DeviceCgroupRules: []string{"a *:* rwm"}, DeviceRequests: []container.DeviceRequest{{Count: -1, Capabilities: [][]string{{"gpu"}}}}, Sysctls: map[string]string{"net.ipv4.ip_forward": "1"}, + LogConfig: container.LogConfig{Type: "syslog", Config: map[string]string{"syslog-address": "tcp://169.254.169.254:514"}}, + OomScoreAdj: -1000, + OomKillDisable: new(true), } sanitizeOptionsHostConfig(logger, hostConfig, &container.HostConfig{}) @@ -699,7 +702,9 @@ func TestMergeContainerConfigsStripsDangerousOptionsWhenUnprivileged(t *testing. const dangerousOptions = "--pid=host --ipc=host --uts=host --cgroupns=host " + "--userns=host --cap-add=ALL --security-opt seccomp=unconfined " + "--security-opt apparmor=unconfined --volumes-from other --isolation process " + - "--runtime runc --cgroup-parent /custom --sysctl net.ipv4.ip_forward=1" + "--runtime runc --cgroup-parent /custom --sysctl net.ipv4.ip_forward=1 " + + "--log-driver=syslog --log-opt syslog-address=tcp://169.254.169.254:514 " + + "--oom-score-adj=-1000 --oom-kill-disable" // whatever the workflow adds, an unprivileged container comes out exactly as the runner's // own options alone describe it, field for field