Forum

Notifications
Clear all

Anyone else having issues with OpenHands and Docker socket permissions?

3 Posts
3 Users
0 Reactions
21 Views
(@container_evan)
Eminent Member
Joined: 3 months ago
Posts: 24
Topic starter   [#1505]

OpenHands default setup runs its worker containers with `privileged: true` and mounts `/var/run/docker.sock` from the host. This is a full breakout risk.

If you're trying to lock it down, you'll hit permission errors. The container's user (`openhands-worker`, UID 1001) isn't in the host's `docker` group. Even if you add it, the group ID inside the container won't match the host's `docker` group GID (typically 998).

Quick fix is to run the worker as root (bad) or set the host docker.sock to world-readable (worse).

Proper fix requires building a custom worker image:
* Ensure the `openhands-worker` user has GID matching host's `docker` group (e.g., 998).
* Add the user to the `docker` group inside the image.
* Run as non-root `USER openhands-worker`.
* Mount socket read-only.

Example Dockerfile addition:
```dockerfile
RUN groupadd -g 998 docker &&
usermod -aG docker openhands-worker
USER openhands-worker
```

Then update your compose to mount socket read-only and drop `privileged: true`.
```yaml
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
securityContext:
privileged: false
```

Their default posture is wide open. You have to rebuild to secure it.

/root


USER nobody


   
Quote
(@network_seg)
Eminent Member
Joined: 3 months ago
Posts: 21
 

Good catch on the GID mismatch. It's a classic side effect of not treating the container as part of the host's security domain.

You can also manage this by modifying the host, creating a docker group with the same GID you use inside your custom image. That keeps everything synchronized if you're deploying across multiple nodes.

But honestly, needing a custom build just to avoid a privileged container is a big red flag for their default configuration. It pushes the security burden entirely onto the user.


Isolate everything.


   
ReplyQuote
(@selftaught_sec)
Eminent Member
Joined: 3 months ago
Posts: 18
 

That's exactly the kind of default config that makes me wonder what their threat model even is. They've basically shipped the 'exploit me' preset. Building a custom image is the right path, but it feels like a workaround for a design flaw.

I tried the group sync approach on a small cluster and it's brittle. If the host docker GID differs, which it often does between fresh installs and cloud images, your container breaks again. So you're either baking a specific GID into your image, which won't be portable, or you're forcing a specific GID on the host, which might conflict with something else.

Why didn't they just use a socket proxy like docker-socket-proxy? It lets you expose specific API endpoints to the container without giving it the whole socket. Then you could run it completely unprivileged.



   
ReplyQuote