Safeguard
Developer Tools•

Which GitLab Runner executor isolates jobs: shell, Docker or Kubernetes?

The shell executor gives no clean build and no protected file system. Docker and Kubernetes isolate better. A plain comparison for choosing a runner.

Safeguard Security Team
3 min read

Docker, Docker Autoscaler and Kubernetes executors give each job a clean environment and a protected runner file system. The shell executor does neither, so jobs can reach the runner's token and other jobs' code and cache. No executor is a perfect boundary, because GitLab warns container breakout is possible through flaws or certain configurations.

What each executor does

GitLab's executor page describes them like this. Shell runs builds on the runner host itself. Docker runs each build in a container. Docker Autoscaler wraps the Docker executor and creates instances on demand. Kubernetes creates a pod per job. Instance gives a job full access to a host instance, and suits jobs that need devices or the operating system. SSH, VirtualBox and Parallels are in maintenance mode and get only critical security updates.

Comparison

ExecutorClean build per jobRunner file system protected
DockerYesYes
Docker AutoscalerYesYes
KubernetesYesYes
InstanceDepends on setupNo
ShellNoNo
SSHNoYes

The footnote that matters most: when the file system is not protected, "jobs can access the entire system, including the runner's token and other jobs' cache and code."

What that means in practice

On a shell runner, one job can leave a file for the next. A job from a less trusted project could read the runner's authentication token. GitLab's runner configuration page adds that an exposed token lets an attacker clone the runner and submit fake jobs, and recommends rotating tokens or recreating the runner.

Containers help, but the limits are real. Docker-in-Docker needs privileged mode, and socket binding gives the job control of the host daemon. Those are covered in our Docker build comparison.

A short decision guide

  1. Is the code trusted and the runner single purpose? A shell runner can be acceptable, with the host treated as disposable.
  2. Do several teams or forks share the runner? Use Docker, Docker Autoscaler or Kubernetes, and prefer fresh instances per job.
  3. Do deploy jobs hold production credentials? Put them on a dedicated runner that only takes jobs from protected refs. See instance, group or project runners.
  4. Do you need persistent state between jobs? Be explicit about it, and keep secrets out of the persistent area.
  5. Rebuild the runner image or host on a schedule. See ephemeral versus persistent runners.

Common mistakes

The common mistake is picking the shell executor for speed and later adding more teams to the same host. Another is assuming a container boundary is complete, then running privileged jobs on the same host as deploy credentials. A third is leaving old runners registered after a migration. List your runners each quarter, retire unused ones, and note which executor and trust level each represents.

Safeguard's asset discovery can help you see which repositories exist before you decide where jobs should run. A free scan is at https://gold.safeguard.sh/scan.

Quick check

Is a Docker executor always safe for untrusted code?

No. It isolates better than shell, but GitLab states container breakout is possible through flaws or certain configurations.

Should I keep using SSH or VirtualBox executors?

They are in maintenance mode with critical security updates only, so plan a move.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.