Skip to main content

Analyze Docker environments for real security risks and attack paths.

Project description

DockerScope

Find out what an attacker could do if they got into your Docker containers.

Real-World Use Case

Whether you're a DevOps engineer managing on-premise infrastructure or a homelabber running self-hosted services like Jellyfin, Nextcloud, or Grafana, deploying containers is often as simple as running docker compose up. However, many popular compose files and tutorials include flags like privileged: true, Docker socket mounts, or network_mode: host without explaining the severe security implications behind them.

Most traditional container security scanners focus entirely on finding known vulnerabilities (CVEs) within container images—such as outdated packages or vulnerable libraries. While that is important, it often overlooks a critical class of risk: runtime infrastructure misconfigurations.

DockerScope is an open-source tool designed to fill that exact gap. It analyzes your running Docker environment (or your compose files statically before deployment) and models real attack paths—including privilege escalation, host escape through misconfigurations, and Docker daemon takeover. By simulating the steps an attacker would take after gaining initial code execution, it highlights exactly what's dangerous, shows the specific commands used for escape, and provides actionable steps to fix it.

What it detects

Risk Severity What it means Real-world example
Docker socket mount CRITICAL Container can control the Docker daemon Container with /var/run/docker.sock — attacker creates a new privileged container
Privileged mode CRITICAL Container has near-root access to host privileged: true — attacker uses nsenter to get a host shell
SYS_ADMIN capability CRITICAL Can mount host filesystems cap_add: [SYS_ADMIN] — attacker mounts host disk
Host PID namespace CRITICAL Container sees all host processes pid: host — attacker uses nsenter to get host shell
Dangerous host mounts CRITICAL Sensitive host paths writable from container /etc mounted writable — attacker modifies /etc/shadow
Host network mode HIGH Container shares the host network stack Can sniff traffic, bind to any host port, access localhost services
SYS_PTRACE capability HIGH Can trace and inject into other processes Combined with host PID, enables host process injection

Note on nsenter: When a container runs with privileged: true and shares the host PID namespace, nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash gives the attacker a full root shell on the host. The command targets PID 1 (the host's init process) and enters its namespaces — effectively leaving the container entirely. This is not a theoretical risk; it's one command from container to host root.

Quick start

# Install via pip
pip install dockerscope

# See what containers you have
dockerscope topology

# Scan everything for risks and attack paths
dockerscope scan

# Scan a specific container
dockerscope scan jellyfin

# Scan a compose file BEFORE deploying (no Docker needed)
dockerscope scan-compose docker-compose.yml

# Scan an entire directory of compose files at once
dockerscope scan-compose ./stacks/

Installation

Via pip (recommended)

pip install dockerscope

This is the recommended way to use DockerScope. It gives you full access to both static compose scanning (scan-compose) and live container auditing (scan, topology).

Via Docker

If you still want to run a live audit on your running containers, you can mount the Docker socket:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock dockerscope scan

Note: Yes, DockerScope flags socket mounts as a critical risk — because they are. We don't want to recommend people blindly mount their socket just to run a security scan. For offline auditing, use scan-compose via pip instead — no Docker socket needed.

From source

git clone https://github.com/tal20100/DockerScope.git
cd DockerScope
pip install -e ".[dev]"

Requirements:

  • Python 3.11+
  • Docker must be running for scan and topology commands. scan-compose works completely offline.
  • For live scanning, your user must be in the docker group, or run with sudo:
    sudo usermod -aG docker $USER
    # Log out and back in for this to take effect
    

Commands

dockerscope topology

Quick overview of all containers on your host — running and stopped. Shows each container's image, network mode, published ports, and security-relevant flags at a glance.

$ dockerscope topology

╭──────────────── Docker Topology ────────────────╮
│ 4 container(s)  3 running  1 stopped            │
╰─────────────────────────────────────────────────╯
┌────────────┬──────────────┬─────────┬─────────┬──────────────────┬─────────┐
│ Container  │ Image        │ Status  │ Network │ Ports            │ Flags   │
├────────────┼──────────────┼─────────┼─────────┼──────────────────┼─────────┤
│ nginx      │ nginx:1.25   │ running │ bridge  │ 0.0.0.0:80->80   │ clean   │
│ jellyfin   │ jellyfin/..  │ running │ host    │                  │ HOSTNET │
│ nextcloud  │ nextcloud:28 │ running │ bridge  │ 0.0.0.0:443->443 │ clean   │
│ watchtower │ watchtower   │ running │ bridge  │                  │ SOCK    │
└────────────┴──────────────┴─────────┴─────────┴──────────────────┴─────────┘

Flags: PRIV=privileged  SOCK=docker.sock  HOSTNET=host network  clean=no issues
Run 'dockerscope scan' to see full risk analysis and attack paths.

dockerscope scan [CONTAINER]

Scan all containers (or a specific one) for security risks and escape paths. Every finding includes:

  • What's dangerous — plain-language explanation
  • Attack commands — exactly what an attacker would run
  • How to fix it — specific remediation steps
dockerscope scan                # Scan all containers
dockerscope scan jellyfin       # Scan specific container

You can export the attack graph for visualization:

dockerscope scan --export json -o graph.json
dockerscope scan --export dot -o graph.dot
dot -Tpng graph.dot -o graph.png    # Render with Graphviz

Example output

============================================================
jellyfin  jellyfin/jellyfin:latest
============================================================

CRITICAL  Container runs in privileged mode.
  Container: jellyfin

  An attacker inside this container has full access to all host
  devices and can escape to the host with a single command.

  Attack command:
    nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash

  Fix:
    Remove 'privileged: true' from your docker-compose.yml. If the
    container needs specific device access, use 'devices:' to grant
    only what is needed.

╔═══════════════ Escape Paths: 1 ═══════════════╗
║ # │ Risk │ Path                         │ Hops ║
╠═══╪══════╪══════════════════════════════╪══════╣
║ 1 │  90% │ jellyfin -> host_root        │    1 ║
╚═══╧══════╧══════════════════════════════╧══════╝

dockerscope scan-compose PATH

Scan compose files for security risks without Docker running. Parses YAML statically and applies the same risk detection. Accepts a single file or a directory — when given a directory, it recursively finds all compose files (docker-compose.yml, docker-compose.yaml, compose.yaml, compose-*.yaml, etc.) and scans each one.

Exits with code 1 if any CRITICAL risk is found — plug it into your CI pipeline to block dangerous deployments.

# Scan a single file
dockerscope scan-compose docker-compose.yml

# Scan an entire directory tree
dockerscope scan-compose ./stacks/
┌─ Scanning directory: ./stacks/ — 3 compose file(s) found ─┐

── ./stacks/nginx/docker-compose.yml ──  (1 service(s))
  nginx — no issues found

── ./stacks/dev/docker-compose.yml ──  (1 service(s))
  CRITICAL: Container runs in privileged mode.
  ...

┌──────────── Summary ────────────┐
│ Critical: 1  High: 0            │
│                                 │
│ Do not deploy without fixing    │
│ critical issues                 │
└─────────────────────────────────┘

Understanding the output

Attack paths

When you run dockerscope scan, the tool builds a directed graph of all possible escape paths. Each path shows how an attacker could move from their initial position (inside a compromised container) toward a critical target (host root access or Docker daemon control).

Example path: jellyfin → host_root (1 hop, privileged escape)

This means: if an attacker gets code execution inside the Jellyfin container, they can use nsenter to escape directly to the host because the container runs in privileged mode.

Risk scores range from 0% to 100% and combine:

  • Exploitability — how easy is each step? (socket mount = trivial, capability abuse = requires knowledge)
  • Impact — what does the attacker gain? (host root = maximum impact)
  • Path length — shorter paths are more dangerous (fewer steps to compromise)

Whitelist / known-safe containers

Some containers legitimately need elevated privileges. For example, Portainer and Watchtower need the Docker socket to function — that's their whole purpose. You can acknowledge these with a whitelist so they don't clutter your scan results.

Create ~/.dockerscope/config.yaml:

whitelist:
  portainer:
    allow:
      - docker_sock_mount
  watchtower:
    allow:
      - docker_sock_mount

Whitelisted risks are excluded from scan output. The container name must match exactly.

Use in CI/CD

Add scan-compose to your pipeline to catch misconfigurations before deployment:

# .github/workflows/security.yml
name: Docker Security Check
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install dockerscope
      - run: dockerscope scan-compose docker-compose.yml
      # Or scan all compose files in the repo:
      # - run: dockerscope scan-compose .

Exit code 1 on critical risks means the CI job fails automatically.

Disclaimer

DockerScope is an independent open-source project and is not affiliated with, endorsed by, or sponsored by Docker, Inc. Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries. This tool is provided "as is" for security auditing and educational purposes only.

License

MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dockerscope-1.1.0.tar.gz (34.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dockerscope-1.1.0-py3-none-any.whl (26.4 kB view details)

Uploaded Python 3

File details

Details for the file dockerscope-1.1.0.tar.gz.

File metadata

  • Download URL: dockerscope-1.1.0.tar.gz
  • Upload date:
  • Size: 34.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dockerscope-1.1.0.tar.gz
Algorithm Hash digest
SHA256 324ac8363544f9392b1bd79e6d5dc942b6d0c6229c3026bb7bacb2a0dba4581a
MD5 14c5672211140ea7a466e1deb20c3266
BLAKE2b-256 d3cc380c98e89e0c7e052ffa600deb44f3174faff7fd3b15436eb1320332d80f

See more details on using hashes here.

Provenance

The following attestation bundles were made for dockerscope-1.1.0.tar.gz:

Publisher: release.yml on tal20100/DockerScope

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dockerscope-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: dockerscope-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dockerscope-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2572b4a60d5cae54dc67df5fa17303dfc5d8d1051c13b8d627afc30eeb8fe6bd
MD5 14db8ed696c6496156a0d3efe4265e88
BLAKE2b-256 c1ae5e556276b377ea438b47a9da28d77a4c0f60bf08268bf21bde7245a52c0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for dockerscope-1.1.0-py3-none-any.whl:

Publisher: release.yml on tal20100/DockerScope

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page