Skip to content

Put the Docker socket behind an allowlisting proxy — Alloy can still POST to it #193

Description

@Gerrrt

Follow-up to #188 / #192, which took every capability off Alloy. That closed the
direct read of ~/.config/sops/age/keys.txt off the /rootfs mount. It did not
close the larger half.

Alloy still mounts the Docker socket:

- /var/run/docker.sock:/var/run/docker.sock:ro

:ro is close to decorative here. It applies to the socket file, not to the
API behind it. Anything that can talk to that API can:

POST /containers/create  {"HostConfig":{"Binds":["/:/host"],"Privileged":true}}

which is root on the host, and the age key with it. So SECURITY.md's statement
that file permissions are all that protect the plaintext artefacts holds for
every process on this host except a compromised Alloy.

Why Alloy needs the socket at all

Three components, and none of them need write:

component uses
prometheus.exporter.cadvisor container names and labels — every rule in containers.rules.yaml filters on name!=""
discovery.docker enumerates containers to tail
loki.source.docker streams stdout/stderr

So the shape of the fix is an allowlisting proxy in front of the socket,
permitting roughly GET /version, /info, /containers/json,
/containers/{id}/json, /containers/{id}/logs, /events, and nothing else.
Alloy then talks to the proxy over the compose network and never sees the socket.

What makes this its own change rather than part of #188

Note on what a proxy does and does not buy

It moves the trust boundary rather than removing it — the proxy container holds
the socket instead. What it buys is that Alloy, which is the component with a
network listener, a rootfs mount and the largest attack surface in the stack, no
longer has a path to POST. That is worth having, and it should be described
that way rather than as "the socket is now safe".

Done when

  • Alloy reaches the Docker API only through a proxy that permits GETs
  • The proxy image is pinned by digest in compose.yaml
  • Container names, cAdvisor series and docker log flow measured before and
    after, not assumed
  • docs/security.md and SECURITY.md updated — both currently say this is
    tracked and not done

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions