GitHub Actions is an extremely popular automation tool for running CI/CD pipelines. At the heart of GitHub Actions is something called the Actions Runner—a small application that actually executes your jobs and workflows. If you use containers inside your workflows (for things like isolated environments or extra services), the Runner interacts with Docker directly to make all that happen.

But in 2022, a serious vulnerability, CVE-2022-39321, was discovered in the Actions Runner. This issue could let a malicious actor escape Docker command arguments just by tricking the Runner with a specially crafted environment variable. In this article, I’ll break down the vulnerability in simple language, show you how the exploit worked, and discuss how to stay safe.

What Is the Vulnerability?

GitHub Actions Runners launch jobs in containers with parameters sent to the docker CLI. Before the patch, the logic for encoding environment variables into these Docker commands had a bug. That bug allowed an attacker to:

Inject additional, unintended arguments into docker commands by abusing environment variable values.

This injection lets anyone who can control job container/service container environment variables execute code or modify the Docker setup—potentially escalating privileges or breaking isolation.

Also vulnerable: 2.293. and below, 2.289.3 and below, 2.285.1 and below, 2.283.3 and below

> If you use container jobs/actions or service containers with any untrusted inputs making it into the environment, you may be at risk.

How the Exploit Works

Let’s say you have a workflow that takes a value from a PR or an issue via a GitHub Actions Input, and you pass that value to an environment variable inside a job container. Bad idea if your runner is outdated!

Example Vulnerable Workflow

jobs:
  test:
    runs-on: [self-hosted, linux]
    container:
      image: node:16
      env:
        APP_CONFIG: ${{ github.event.inputs.app_config }}
    steps:
      - run: echo "Running tests"

If the workflow input app_config could be set by untrusted users, someone could submit a value like this:

"foo" --privileged --entrypoint /bin/sh -c "evil commands"

Before the patch, the runner would essentially construct and execute this type of Docker command

docker run -e "APP_CONFIG=foo" myimage

But, with no proper quoting or escaping, the payload actually results in

docker run -e APP_CONFIG=foo --privileged --entrypoint /bin/sh -c "evil commands" myimage

Now, Docker receives new, unexpected flags like --privileged, which gives the container full host access, or uses a custom entrypoint to execute arbitrary code at startup!

Below is a simplified way to show the problem with a plain Docker command

export APP_CONFIG='foo" --privileged --entrypoint=sh -c "echo HACKED'
docker run -e "APP_CONFIG=$APP_CONFIG" myimage:latest

If handled incorrectly, your container now runs in privileged mode with a different entrypoint—all due to bad quoting in how environment variables are passed to Docker.

GitHub fixed this in Actions Runner versions: 2.283.4, 2.285.2, 2.289.4, 2.293.1, and 2.296.2

- Changelog with the fix
- Upgraded runners now safely encode and escape all environment variables so they can’t break out of their intended place in the docker command.

Upgrade your GitHub Actions Runner NOW to at least the patched versions listed above.

- If you’re an enterprise user (GHES or GHAE), see the GitHub advisory and make sure hotfixes are applied.
- As a stop-gap, stop using any container jobs, container actions, or service containers with untrusted input until you’ve patched all runners.

If you must use untrusted data, always validate and sanitize inputs first

env:
  SAFE_VALUE: ${{ github.event.inputs.safe_value }}

And only ever allow a fixed set of possible values (using input validation in your workflow logic or action code).

More Information

- Original Advisory
- GitHub Runner Releases
- CVE-2022-39321 NVD Entry


Summary:
If you use GitHub Actions with containers, make sure your runner software is up to date. Don’t trust user input in environment variables—always validate and sanitize it. CVE-2022-39321 is a good demonstration that even simple quoting bugs can have big security implications in automation.

---
Let me know if you want a demo repository or more technical details. Stay safe and keep your runners patched!

Timeline

Published on: 10/25/2022 17:15:00 UTC
Last modified on: 10/28/2022 18:27:00 UTC