Docker Bridge Network Security: One Setting That Changes Everything

Docker's default bridge network leaves every container open to every other container — one compromised container becomes a launchpad for lateral movement. Learn how the single `icc: false` setting stops container-to-container attacks at the virtual switch level.

Your Docker containers are wide open to each other by default. The docker0 bridge lets every container on the same host communicate with every other container — no firewall, no authentication, no questions asked. One compromised container becomes a launchpad for lateral movement across your entire host. But a single daemon setting changes everything.

Docker's default bridge network is the most overlooked attack surface in container deployments. Most teams focus on application vulnerabilities, image CVEs, or secret leaks, while ignoring that all their containers share a flat, trust-everything network. In this article, you will learn how Docker bridge networking works, why the default is dangerous, and the one setting —--icc=false — that fundamentally changes your container security posture.

Why Docker Bridge Network Security Matters

Every Docker installation creates a virtual Ethernet bridge calleddocker0. When you run a container without specifying a --network flag, Docker attaches it to this default bridge. The default configuration allows full, unrestricted communicationbetween all containers on that bridge. This is not a bug — it is by design, and it has been the default since Docker's earliest releases.

The security implications are severe. According to theCIS Docker Benchmark, unrestricted inter-container communication is one of the top risks in container deployments. A single compromised web application container can probe internal databases, message queues, cache servers, and other containers that were never meant to be publicly accessible. The attacker does not need to exploit a kernel vulnerability — they just connect to the next container over the virtual bridge.

In real-world breach data from 2024–2026, lateral movement through container-to-container networks was a factor in over 34% of container-related incidents tracked by NVD and cloud security advisories. The attack path is consistent: an application vulnerability (RCE, SSRF, SQLi) in one container → shell access → internal network scanning → compromised database or secrets container.

The Default Bridge Attack Chain

1 · Initial Compromise
Web app RCE or SSRF gives shell access to container A.
2 · Lateral Scan
Attacker scans 172.17.0.0/16, discovers container B runs PostgreSQL.
3 · Data Exfiltration
Weak or default DB credentials give access to production data.
4 · Persistence
Crypto miner or backdoor container deployed on the same host.

The Default Bridge — Designed for Convenience, Not Security

When you install Docker, it creates thedocker0 bridge with IP range 172.17.0.0/16. Every container attached to the default bridge gets an IP from this range and can reach any other container on the same bridge. Docker automatically programs iptables rules to enable this traffic. No authentication, no encryption, no network policy — just raw IP connectivity.

The relevant iptables rule looks like this:

# Default Docker iptables rules (shortened for clarity)
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

The first rule —-i docker0 -o docker0 -j ACCEPT — is the critical one. It allows all traffic coming from any container to any other container on the same bridge. There is no filtering, no application-level inspection, and no identity check. Any process inside any container can connect to any port on any other container.

The One Setting That Changes Everything:--icc=false

The setting is calledInter-Container Communication (ICC), and it controls whether containers on the default bridge can talk to each other. The default is--icc=true. Changing it to false adds a single iptables DROP rule that blocks all container-to-container traffic on the default bridge.

# After --icc=false, Docker inserts this DROP rule:
-A DOCKER-ISOLATION -i docker0 -o docker0 -j DROP

That is the one setting. One boolean flag. It stops lateral movement dead at the virtual switch level. Containers can still reach the internet (outbound traffic works through NAT), and the host can reach containers via mapped ports. But container A can no longer connect to container B on172.17.0.2:5432 — the connection is silently dropped at the bridge.

How to Enable ICC Isolation

There are two ways to set--icc=false:

Option 1: Daemon configuration file(recommended — persists across restarts):

# /etc/docker/daemon.json
{
  "icc": false,
  "iptables": true
}

Then restart Docker:

sudo systemctl restart docker

Option 2: Docker daemon command-line flag:

dockerd --icc=false --iptables=true

Before vs After: Default Bridge Isolation

❌ icc: true (default)
container-a → container-b:5432 ✅ Allowed
container-b → container-c:6379 ✅ Allowed
container-c → internet ✅ Allowed
Risk: Full lateral movement
✅ icc: false (hardened)
container-a → container-b:5432 ❌ Blocked
container-b → container-c:6379 ❌ Blocked
container-c → internet ✅ Allowed
Safe: No lateral movement

Beyond ICC — Building a Secure Bridge Network

Settingicc=false on the default bridge is the most impactful change, but it is not the only one. A defense-in-depth approach to Docker bridge networking combines multiple controls.

1. Use User-Defined Bridge Networks

Docker's user-defined bridge networks (created withdocker network create) offer several security advantages over the default bridge:

  • Automatic DNS resolution— Containers resolve each other by name, not IP. This means you can run containers that need to communicate on the same network while keeping them isolated from everything else.
  • Selective connectivity— Only containers explicitly attached to the same user-defined network can communicate. Containers on different user-defined networks are completely isolated from each other.
  • No ICC flag requirement— User-defined bridges already block inter-container communication by default. You only need to explicitly connect containers that should talk to each other.
# Create a user-defined bridge for the web stack
docker network create --driver bridge web-tier

# Run containers on this network
docker run -d --name api --network web-tier my-api:latest
docker run -d --name frontend --network web-tier my-frontend:latest

# These two containers can resolve and communicate
# A container NOT on web-tier cannot reach them

2. Disable Userland Proxy

Theuserland-proxy feature starts a small docker-proxy process for every published port. Disabling it reduces the attack surface by removing unnecessary processes and uses direct iptables DNAT rules instead:

{
  "userland-proxy": false,
  "iptables": true
}

3. Restrict Default Network Creation

Prevent developers from accidentally running containers on the default bridge by using the--network=none pattern or by monitoring for containers on docker0:

# CIS Benchmark recommendation - audit for default bridge usage
docker network inspect bridge --format '{{range .Containers}}{{.Name}}{{end}}'

4. Combine with Host-Level Firewall Rules

Even withicc=false, you can add UFW or nftables rules to restrict outbound container traffic and block known bad destinations:

# Block container traffic to known mining pools
sudo iptables -I FORWARD -i docker0 -d 203.0.113.0/24 -j DROP

Docker Bridge Security Layers

Layer 1 · ICC Isolation
Seticc: false in daemon.json to block all container-to-container traffic on the default bridge. This is your first and most impactful line of defense.
Layer 2 · Custom Networks
Move all workloads to user-defined bridges with explicit container attachments. Usedocker network create per application tier.
Layer 3 · No Proxy
Disableuserland-proxy to eliminate the docker-proxy process for every mapped port. Fewer processes = smaller attack surface.
Layer 4 · Host Firewall
Add iptables/nftables rules on the FORWARD chain to restrict container egress. Block known C2 infrastructure and mining pools.

Compliance and Standards Mapping

Restricting inter-container communication maps directly to multiple compliance frameworks:

  • CIS Docker Benchmark v1.6+— Section 2.1 (Network Configuration) recommends settingicc=false and using user-defined networks. This is a Level 1 recommendation (practical and enforceable without breaking functionality).
  • NIST SP 800-190— Section 3.2.1 (Container Network Security) requires network segmentation between containers. The default bridge withicc=false satisfies this control at the host level.
  • PCI DSS v4.0— Requirement 1.2.1 mandates network segmentation and controls between trusted and untrusted components. Containers on the default bridge without ICC isolation violate this requirement.
  • SOC 2— The CC6 (Logical and Physical Access) criteria require network-level segmentation to prevent unauthorized access between system components.

Complete Docker Bridge Security Checklist

Use this checklist to harden your Docker bridge networking. Each item has an estimated effort rating so you can prioritize based on your risk profile.

  • Seticc: false in daemon.json — The single highest-impact change. Takes 5 minutes, prevents all lateral movement on the default bridge. docker system info | grep -i icc to verify.
  • Migrate to user-defined bridge networks— Create one network per application tier (web, API, db). Connect only containers that need to communicate. Achieve micro-segmentation at the virtual network level.
  • Disable userland proxy— Setuserland-proxy: false in daemon.json. Fewer running processes, direct iptables DNAT only.
  • Audit default bridge usage— Rundocker network inspect bridge weekly to detect containers still running on docker0. Alert on any container attached to the default bridge.
  • Set explicit network for all containers— In Docker Compose, always set thenetworks: block. Never rely on the implicit default bridge network.
  • Add egress filtering— Block container outbound traffic to known malicious IPs and CIDR ranges using iptables FORWARD chain rules.
  • Enable Docker Content Trust— While not a networking control, DCT ensures only signed images run, reducing the chance of a malicious container reaching your network.
  • Review container port mappings— Only expose ports that are strictly necessary. Use127.0.0.1: binding for internal services: docker run -p 127.0.0.1:5432:5432 ...
  • Monitor bridge traffic— Usetcpdump -i docker0 periodically during incident investigations to detect unexpected inter-container connections.
  • Document network architecture— Maintain a diagram of all Docker networks, which containers are on each, and which ports are exposed. Review quarterly with your security team.

Related ShieldOps Reads

Deepen your container security knowledge with these related articles from the ShieldOps blog:

Frequently Asked Questions

Doesicc=false affect containers on user-defined networks?

No.icc only applies to the default docker0 bridge. User-defined bridge networks have their own isolation model — containers on different user-defined networks cannot communicate unless you explicitly connect them. Setting icc=false on the daemon has no effect on user-defined networks.

Willicc=false break Docker Compose applications?

Yes, if your Compose file relies on the default bridge network (no explicitnetworks: section). Compose creates its own user-defined bridge network by default since Compose v2, so most modern Compose applications are unaffected. If you use network_mode: bridge explicitly, you will need to either remove that setting or connect services to the same user-defined network.

How do I verifyicc is working correctly?

Run a quick test with two containers on the default bridge. Container A should not be able to reach Container B's ports after you seticc=false. Use docker exec container-a ping -c 2 container-b-ip — it should time out. For a more thorough test, try TCP port connections with nc -zv.

Doesicc=false affect container-to-internet traffic?

No. The iptables DROP rule only applies to traffic that entersdocker0 and leaves docker0 (container-to-container). Outbound traffic to the internet (container → docker0 → eth0) still works through Docker's MASQUERADE (NAT) rules. Inbound traffic from published ports (host → container) also continues to work.

Is there any performance impact from settingicc=false?

Negligible. The DROP rule is evaluated at line speed by the kernel's netfilter, adding microseconds per packet. In practice, users report zero measurable performance difference. Theuserland-proxy: false change can actually improveperformance by eliminating the context switch between the proxy process and the kernel for every connection.

How is this different from Kubernetes Network Policies?

Kubernetes Network Policies work at the cluster level and use CNI plugins (Calico, Cilium, etc.) to enforce rules. Docker'sicc=false is a host-level iptables rule — it is simpler, coarser, and applies only to the local Docker daemon. For multi-node deployments, Kubernetes Network Policies or service mesh mTLS are more appropriate. For a single host or a development environment, icc=false is the fastest path to basic isolation.

Conclusion

One boolean flag —icc: false — changes your Docker bridge network from a flat, trust-everything fabric into an isolated environment where lateral movement is blocked at the virtual switch level. Combined with user-defined bridge networks, disabled userland proxy, and host-level firewall rules, this single setting eliminates the most common container-to-container attack path.

Start today: add"icc": false to your /etc/docker/daemon.json, restart the daemon, and audit your containers for default bridge usage. Then move your production workloads to user-defined bridge networks where you control exactly which containers communicate.

Ready to analyze your Docker security posture comprehensively?Start your free security scan with ShieldOps— our platform scans your Dockerfiles, Compose files, and runtime configurations for 200+ security rules including bridge network hardening.Register for free.

Ready to apply these concepts?

Try ShieldOps AI and start scanning your infrastructure right away.

Start Free Scan

Your take

Rate this article or leave a comment

Have more questions? Check our

FAQ
🤖