glsec

Rules / GL055

GL055 Host Docker socket mounted into a CI job

Severity: warn
OWASP: CICD-SEC-5 – Insufficient PBAC
CWE: CWE-250 – Execution with Unnecessary Privileges

Risk

Mounting the host Docker socket (/var/run/docker.sock) into a CI job grants that job full control over the Docker daemon on the runner host. Any job with access to the socket can spawn privileged containers, escape its own containment, access secrets from other running jobs, and persist backdoors on the host.

This is a known real-world attack vector documented in NCC Group's 10 real-world CI/CD pipeline compromises.

Trigger example

build:
  image: docker:26.0
  variables:
    DOCKER_HOST: unix:///var/run/docker.sock   # flagged
  script:
    - docker build -t myapp .

The rule flags a DOCKER_HOST variable pointing at the unix socket. The socket is mounted into the job by the runner's config.toml (volumes = ["/var/run/docker.sock:/var/run/docker.sock"]), which is not part of .gitlab-ci.yml and therefore outside glsec's static analysis — but the DOCKER_HOST reference in the pipeline is the reliable, detectable signal that a job is wired to control the host daemon. (Service-level volumes: is not valid .gitlab-ci.yml schema and cannot appear in a pipeline file.)

Safe alternative

Use Docker-in-Docker via the docker:dind service over a TLS-protected TCP endpoint, without mounting the host socket:

build:
  image: docker:26.0
  services:
    - docker:26.0-dind
  variables:
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker build -t myapp .

Rootless build tools such as Kaniko or Buildah avoid the Docker daemon entirely — see GL054.

Notes

Documentation for glsec 1.23.0. Source of this page · Rule implementation