[security] Monitoring docker containers #3355

Open
opened 2026-02-28 03:26:45 -05:00 by deekerman · 17 comments
Owner

Originally created by @thielj on GitHub (May 22, 2024).

Originally assigned to: @Angel-Mathew007 on GitHub.

🛡️ Security Policy

Description

Access to the docker socket is almost equivalent to a root shell, no matter if the socket is mounted read-only or made available through a (SSL) network connection. Instead of the procedure suggested in the docs, a much better approach would be to expose the socket through a proxy that makes only the necessary read-only API available to Uptimee Kuma through an internal docker network.

I'm using Tecnativa/docker-socket-proxy for that purpose. See the docs there.

I'm deliberately reporting this as a "documentation bug" and not a direct vulnerability to Uptime Kuma as it requires the host system or ANY container or any other system having access to the exposed socket to be compromised. However, suggesting this to users who are probably unaware of the implications is simply bad practice as it allows an attacker to immediately acquire root privileges.

👟 Reproduction steps

docker -H tcp://127.0.0.1 run -v '/:/mnt' busybox touch /mnt/test
ls -al /test

👀 Expected behavior

n/a

😓 Actual Behavior

n/a

🐻 Uptime-Kuma Version

all versions

💻 Operating System and Arch

Any Linux

🌐 Browser

n/a

🖥️ Deployment Environment

Monitoring docker containers

📝 Relevant log output

No response

Originally created by @thielj on GitHub (May 22, 2024). Originally assigned to: @Angel-Mathew007 on GitHub. ### 📑 I have found these related issues/pull requests - https://github.com/louislam/uptime-kuma/issues/2061 - https://github.com/louislam/uptime-kuma/issues/1117 ### 🛡️ Security Policy - [X] I agree to have read this project [Security Policy](https://github.com/louislam/uptime-kuma/security/policy) ### Description Access to the docker socket is almost equivalent to a root shell, no matter if the socket is mounted read-only or made available through a (SSL) network connection. Instead of the procedure suggested [in the docs](https://github.com/louislam/uptime-kuma/wiki/How-to-Monitor-Docker-Containers), a much better approach would be to expose the socket through a proxy that makes only the necessary read-only API available to Uptimee Kuma through an internal docker network. I'm using [Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) for that purpose. See the docs there. I'm deliberately reporting this as a "documentation bug" and not a direct vulnerability to Uptime Kuma as it requires the host system or *ANY* container or any other system having access to the exposed socket to be compromised. However, suggesting this to users who are probably unaware of the implications is simply bad practice as it allows an attacker to immediately acquire root privileges. ### 👟 Reproduction steps ```sh docker -H tcp://127.0.0.1 run -v '/:/mnt' busybox touch /mnt/test ls -al /test ``` ### 👀 Expected behavior n/a ### 😓 Actual Behavior n/a ### 🐻 Uptime-Kuma Version all versions ### 💻 Operating System and Arch Any Linux ### 🌐 Browser n/a ### 🖥️ Deployment Environment Monitoring docker containers ### 📝 Relevant log output _No response_
Author
Owner

@thielj commented on GitHub (May 22, 2024):

@CommanderStorm as discussed last week

@thielj commented on GitHub (May 22, 2024): @CommanderStorm as discussed last week
Author
Owner

@louislam commented on GitHub (May 22, 2024):

I think Portainer did that in the same way.

docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

May need a reason why Portainer is ok to do that, but Uptime Kuma cannot.

@louislam commented on GitHub (May 22, 2024): I think Portainer did that in the same way. ``` docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest ``` May need a reason why Portainer is ok to do that, but Uptime Kuma cannot.
Author
Owner

@thielj commented on GitHub (May 22, 2024):

Portainer, Yacht, etc aren't really okay to do that either and I'm proxying them, too. However...

  • Portainer needs much wider access to the docker API for creating containers, networks, etc; Without almost full access, they couldn't provide much functionality at all. My choice is between granting such access or not using Portainer at all.

  • Uptime Kuma OTOH only requires minimal access to check if a container is running. There simply is no need to give a running UK container root access to the host through the docker socket - needing to start it as root is already bad enough ;)

  • admins hopefully secure and restrict access to the Portainer UI to internal networks while it isn't unusual for Uptime Kuma to be fully exposed to the public (status pages, API, badges, etc)

  • I have some hopes that Portainer is spending some of their VC on security audits

If an app would ask you to enter your root password or supply an ssh key for a root shell, you would think twice before doing so. People don't realize that the very same applies to mounting the docker socket.

No offense man, you're doing great otherwise!

@thielj commented on GitHub (May 22, 2024): Portainer, Yacht, etc aren't really *okay* to do that either and I'm proxying them, too. However... - Portainer needs much wider access to the docker API for creating containers, networks, etc; Without almost full access, they couldn't provide much functionality at all. My choice is between granting such access or not using Portainer at all. - Uptime Kuma OTOH only requires minimal access to check if a container is running. There simply is no need to give a running UK container root access to the host through the docker socket - needing to start it as root is already bad enough ;) - admins hopefully secure and restrict access to the Portainer UI to internal networks while it isn't unusual for Uptime Kuma to be fully exposed to the public (status pages, API, badges, etc) - I have some hopes that Portainer is spending some of their VC on security audits If an app would ask you to enter your root password or supply an ssh key for a root shell, you would think twice before doing so. People don't realize that the very same applies to mounting the docker socket. No offense man, you're doing great otherwise!
Author
Owner

@CommanderStorm commented on GitHub (May 22, 2024):

I don't know how to set up this proxying.
I think adding it as a tip to the docs such as

Tip

You can reduce your attack surface ...

=> I think this would be valuable.

You seem to have to have the whole thing figured out. Could you provide a PR to enhance https://github.com/louislam/uptime-kuma-wiki/blob/master/How-to-Monitor-Docker-Containers.md?

@CommanderStorm commented on GitHub (May 22, 2024): I don't know how to set up this proxying. I think adding it as a tip to the docs such as > [!TIP] > You can reduce your attack surface ... => I think this would be valuable. You seem to have to have the whole thing figured out. Could you provide a PR to enhance https://github.com/louislam/uptime-kuma-wiki/blob/master/How-to-Monitor-Docker-Containers.md?
Author
Owner

@thielj commented on GitHub (May 22, 2024):

The API call currently used - GET /containers/{id}/json exposes environment variables and a whole lot more.

github.com/louislam/uptime-kuma@88b7c047a8/server/model/monitor.js (L724)

github.com/louislam/uptime-kuma@88b7c047a8/server/docker.js (L72)

Ideally, the use of docker API within Uptime Kuma would be restricted to GET /_ping to check the connection parameters and a sanitized GET /containers/{name}/json.

Happy to contribute a fully configured and locked down proxy container with setup information.

@thielj commented on GitHub (May 22, 2024): The API call currently used - [GET /containers/{id}/json](https://docs.docker.com/engine/api/v1.45/#tag/Container/operation/ContainerInspect) exposes environment variables and a whole lot more. https://github.com/louislam/uptime-kuma/blob/88b7c047a859d83862f917b876b921ec026fef5a/server/model/monitor.js#L724 https://github.com/louislam/uptime-kuma/blob/88b7c047a859d83862f917b876b921ec026fef5a/server/docker.js#L72 Ideally, the use of docker API within Uptime Kuma would be restricted to [GET /_ping](https://docs.docker.com/engine/api/v1.45/#tag/System/operation/SystemPing) to check the connection parameters and a sanitized [GET /containers/{name}/json](https://docs.docker.com/engine/api/v1.45/#tag/Container/operation/ContainerList). Happy to contribute a fully configured and locked down proxy container with setup information.
Author
Owner

@thielj commented on GitHub (May 22, 2024):

Try this, even if you're already proxying: curl 'http://localhost:2375/containers/json' | jq

It includes detailed information, including labels used to provide passwords for auth middlewares, network information, credentials passed in commands, credentials used for CIFS/NAS mounts, mount paths, exact version information, etc.

There currently isn't a docker API that exposes less information.

@thielj commented on GitHub (May 22, 2024): Try this, even if you're already proxying: `curl 'http://localhost:2375/containers/json' | jq` It includes detailed information, including labels used to provide passwords for auth middlewares, network information, credentials passed in commands, credentials used for CIFS/NAS mounts, mount paths, exact version information, etc. There currently isn't a docker API that exposes less information.
Author
Owner

@thielj commented on GitHub (May 23, 2024):

This should do it: https://github.com/thielj/docker-health-proxy/pkgs/container/docker-health-proxy

It currently leaves the /containers/json API enabled to simplify testing with current U-K release.
I suggest replacing this with /_ping which is also official Docker Engine API but doesn't expose any sensitive information. You wouldn't get the 'number of containers' info though. If you think that's significant, that API call would need to be sanitized as well.

github.com/louislam/uptime-kuma@88b7c047a8/server/docker.js (L72)

If you agree, I suggest deferring an update of the docs until /_ping has made it into an Uptime Kuma release and the /containers/json route has been nuked from the proxy.

@thielj commented on GitHub (May 23, 2024): This should do it: https://github.com/thielj/docker-health-proxy/pkgs/container/docker-health-proxy It currently leaves the `/containers/json` API enabled to simplify testing with current U-K release. I suggest replacing this with `/_ping` which is also official Docker Engine API but doesn't expose any sensitive information. You wouldn't get the 'number of containers' info though. If you think that's significant, that API call would need to be sanitized as well. https://github.com/louislam/uptime-kuma/blob/88b7c047a859d83862f917b876b921ec026fef5a/server/docker.js#L72 If you agree, I suggest deferring an update of the docs until `/_ping` has made it into an Uptime Kuma release and the `/containers/json` route has been nuked from the proxy.
Author
Owner

@thielj commented on GitHub (May 28, 2024):

I've built the final version (v1.0.0). It requires /_ping instead of /containers/json?all=true for the connection test. Or rather, you will get a 403 error when you hit Test, as it should be ;)

If you want to test against /containers/json?all=true, use v0.0.0.

@thielj commented on GitHub (May 28, 2024): I've built the [final version (v1.0.0)](https://github.com/thielj/docker-health-proxy/pkgs/container/docker-health-proxy). It requires `/_ping` instead of `/containers/json?all=true` for the connection test. Or rather, you will get a 403 error when you hit Test, as it should be ;) If you want to test against `/containers/json?all=true`, use v0.0.0.
Author
Owner

@thielj commented on GitHub (Jun 7, 2024):

Regarding the docker remote setups you're recommending as "secure"...
https://thehackernews.com/2024/06/commando-cat-cryptojacking-attacks.html

@thielj commented on GitHub (Jun 7, 2024): Regarding the docker remote setups you're recommending as "secure"... https://thehackernews.com/2024/06/commando-cat-cryptojacking-attacks.html
Author
Owner

@ColCh commented on GitHub (Sep 14, 2024):

Thank you very much @thielj for links to tests, much helpful.

I use this approach in my homelab. Might be useful for somebody, may be :)

This approach exposes too much, please also check other comments below.


It uses Tecnativa/docker-socket-proxy Proxy over your Docker socket to restrict which requests it accepts

docker compose for it as follows. Use http://docker-socket-proxy:2375 as url for docker TCP/HTTP connection type

services:
    uptime-kuma:
        image: louislam/uptime-kuma:1
        container_name: uptime-kuma
        volumes:
            - ./data:/app/data
        expose:
            - 3001
        restart: always
        labels:
            - 'com.centurylinklabs.watchtower.enable=true'
        cpu_count: 1
        mem_limit: 512m
        security_opt:
          - no-new-privileges:true
        networks:
            - local-int
            - myint

    docker-socket-proxy:
        image: tecnativa/docker-socket-proxy
        container_name: docker-socket-proxy
        healthcheck:
            test: ["CMD", "nc", "-z", "localhost", "2375"]
        restart: always
        environment:
            CONTAINERS: 1 # Allows access to /containers/*
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /var/run/docker.sock:/var/run/docker.sock:ro
        networks:
            - local-int
        cpu_count: 1
        mem_limit: 512m
        security_opt:
          - no-new-privileges:true
        expose:
            - '2375'
        labels:
            - 'com.centurylinklabs.watchtower.enable=true' # you might NOT want to use watchtower with this one

networks:
    local-int:
    myint: # your reverse-proxy network
        external: true

@ColCh commented on GitHub (Sep 14, 2024): Thank you very much @thielj for links to tests, much helpful. ~~I use this approach in my homelab. Might be useful for somebody, may be :)~~ This approach exposes too much, please also check other comments below. ---- It uses [Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) _Proxy over your Docker socket to restrict which requests it accepts_ docker compose for it as follows. Use `http://docker-socket-proxy:2375` as url for docker **TCP/HTTP** connection type ```yml services: uptime-kuma: image: louislam/uptime-kuma:1 container_name: uptime-kuma volumes: - ./data:/app/data expose: - 3001 restart: always labels: - 'com.centurylinklabs.watchtower.enable=true' cpu_count: 1 mem_limit: 512m security_opt: - no-new-privileges:true networks: - local-int - myint docker-socket-proxy: image: tecnativa/docker-socket-proxy container_name: docker-socket-proxy healthcheck: test: ["CMD", "nc", "-z", "localhost", "2375"] restart: always environment: CONTAINERS: 1 # Allows access to /containers/* volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro networks: - local-int cpu_count: 1 mem_limit: 512m security_opt: - no-new-privileges:true expose: - '2375' labels: - 'com.centurylinklabs.watchtower.enable=true' # you might NOT want to use watchtower with this one networks: local-int: myint: # your reverse-proxy network external: true ```
Author
Owner

@thielj commented on GitHub (Sep 14, 2024):

@ColCh The tecnativa proxy exposes far too much information, including for example secrets passed in environment variables, command line parameters, credentials for network mounts, etc.

The nginx based proxy I created doesn't just restrict API methods, but also sanitizes the results to what's absolutely necessary. See the README.

I had to use nginx because haproxy doesn't support result filtering. You can audit the code if you wish, it's just a couple of lines. Memory footprint is very similar.

There's also a security advisory related to this where I show how a fresh installation of Uptime Kuma can be used to create a root shell through an exposed docker socket.

@thielj commented on GitHub (Sep 14, 2024): @ColCh The tecnativa proxy exposes far too much information, including for example secrets passed in environment variables, command line parameters, credentials for network mounts, etc. The nginx based proxy I created doesn't just restrict API methods, but also sanitizes the results to what's absolutely necessary. See the README. I had to use nginx because haproxy doesn't support result filtering. You can audit the code if you wish, it's just a couple of lines. Memory footprint is very similar. There's also a security advisory related to this where I show how a fresh installation of Uptime Kuma can be used to create a root shell through an exposed docker socket.
Author
Owner

@ColCh commented on GitHub (Sep 14, 2024):

@ColCh The tecnativa proxy exposes far too much information, including for example secrets passed in environment variables, command line parameters, credentials for network mounts, etc.

The nginx based proxy I created doesn't just restrict API methods, but also sanitizes the results to what's absolutely necessary. See the README.

I had to use nginx because haproxy doesn't support result filtering. You can audit the code if you wish, it's just a couple of lines. Memory footprint is very similar.

omg, you're right! really interesting

thank you so much for pointing that out, I will correct my local setup and that comment for sure

@ColCh commented on GitHub (Sep 14, 2024): > @ColCh The tecnativa proxy exposes far too much information, including for example secrets passed in environment variables, command line parameters, credentials for network mounts, etc. > > The nginx based proxy I created doesn't just restrict API methods, but also sanitizes the results to what's absolutely necessary. See the README. > > I had to use nginx because haproxy doesn't support result filtering. You can audit the code if you wish, it's just a couple of lines. Memory footprint is very similar. omg, you're right! really interesting thank you so much for pointing that out, I will correct my local setup and that comment for sure
Author
Owner

@shalafi99 commented on GitHub (Sep 20, 2024):

I've built the final version (v1.0.0). It requires /_ping instead of /containers/json?all=true for the connection test. Or rather, you will get a 403 error when you hit Test, as it should be ;)

If you want to test against /containers/json?all=true, use v0.0.0.

It might be worth of note the "Test" button (inside Uptime Kuma's Docker Host settings) also appears to be an API call which gets denied by the proxy 😄. So go directly for "Save" after inputting the connection info.

@shalafi99 commented on GitHub (Sep 20, 2024): > I've built the [final version (v1.0.0)](https://github.com/thielj/docker-health-proxy/pkgs/container/docker-health-proxy). It requires `/_ping` instead of `/containers/json?all=true` for the connection test. Or rather, you will get a 403 error when you hit Test, as it should be ;) > > If you want to test against `/containers/json?all=true`, use v0.0.0. It might be worth of note the "Test" button (inside Uptime Kuma's Docker Host settings) also appears to be an API call which gets denied by the proxy 😄. So go directly for "Save" after inputting the connection info.
Author
Owner

@thielj commented on GitHub (Sep 23, 2024):

@shalafi99 That's intended as the proxy also blocks the listing of all containers 🚧

I suggested that the Test button uses the official /_ping API call instead, which doesn't leak any information.

@thielj commented on GitHub (Sep 23, 2024): @shalafi99 That's intended as the proxy also blocks the listing of all containers 🚧 I suggested that the Test button uses the official `/_ping` API call instead, which doesn't leak any information.
Author
Owner

@Angel-Mathew007 commented on GitHub (Oct 8, 2025):

can i work on this ?

@Angel-Mathew007 commented on GitHub (Oct 8, 2025): can i work on this ?
Author
Owner

@CommanderStorm commented on GitHub (Oct 8, 2025):

I am not sure what would be required to fix it.
I don't want another docker container, that breaks our simplicity

@CommanderStorm commented on GitHub (Oct 8, 2025): I am not sure what would be required to fix it. I don't want another docker container, that breaks our simplicity
Author
Owner

@thielj commented on GitHub (Oct 8, 2025):

Nothing, really. The health proxy works, doesn't leak any confidential data
like the tecnativa solution and requires less resources.

Use docker's official /_ping API for the Test button. That's all.

On Wed, Oct 8, 2025, 17:22 Frank Elsinga @.***> wrote:

CommanderStorm left a comment (louislam/uptime-kuma#4783)
https://github.com/louislam/uptime-kuma/issues/4783#issuecomment-3382320837

I am not sure what would be required to fix it.
I don't want another docker container, that breaks our simplicity


Reply to this email directly, view it on GitHub
https://github.com/louislam/uptime-kuma/issues/4783#issuecomment-3382320837,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AA6CUVKOOF2EKHS7DSSKWS33WU26FAVCNFSM6AAAAABIDPJJNCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGOBSGMZDAOBTG4
.
You are receiving this because you were mentioned.Message ID:
@.***>

@thielj commented on GitHub (Oct 8, 2025): Nothing, really. The health proxy works, doesn't leak any confidential data like the tecnativa solution and requires less resources. Use docker's official /_ping API for the Test button. That's all. On Wed, Oct 8, 2025, 17:22 Frank Elsinga ***@***.***> wrote: > *CommanderStorm* left a comment (louislam/uptime-kuma#4783) > <https://github.com/louislam/uptime-kuma/issues/4783#issuecomment-3382320837> > > I am not sure what would be required to fix it. > I don't want another docker container, that breaks our simplicity > > — > Reply to this email directly, view it on GitHub > <https://github.com/louislam/uptime-kuma/issues/4783#issuecomment-3382320837>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/AA6CUVKOOF2EKHS7DSSKWS33WU26FAVCNFSM6AAAAABIDPJJNCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGOBSGMZDAOBTG4> > . > You are receiving this because you were mentioned.Message ID: > ***@***.***> >
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/uptime-kuma#3355
No description provided.