Skip to content

Security: Docker container runs as root with excessive capabilities #3969

@pjt222

Description

@pjt222

Summary

Three container security concerns that together increase the blast radius of any in-container compromise.

Finding 1: Dockerfile runs as root

File: Dockerfile

No USER directive — the container runs everything as root, including the entrypoint and agent execution. While root-in-container is common for development/sandbox use cases, it maximizes the impact of container escapes via kernel exploits or Docker daemon vulnerabilities.

Suggested fix:

RUN groupadd --gid 1000 hermes && \
    useradd --uid 1000 --gid 1000 --shell /bin/bash --create-home hermes && \
    chown -R hermes:hermes /opt/hermes /opt/data
USER hermes:hermes

Finding 2: Excessive capabilities on bind-mounted directories

File: tools/environments/docker.py, _SECURITY_ARGS

The Docker environment retains DAC_OVERRIDE, CHOWN, and FOWNER capabilities after dropping ALL. DAC_OVERRIDE allows bypassing file permission checks on bind-mounted host directories (~/.hermes/sandboxes/<task_id>/). A malicious command running as container root can write to any file in mounted directories regardless of host permissions.

Suggested fix: Use --user $(id -u):$(id -g) to run containers as the host user, eliminating the need for these capabilities. If root is required inside, use --userns-remap.

Finding 3: shell=True in docker cleanup (incomplete fix for #1241)

File: tools/environments/docker.py, lines ~513-527

Two subprocess.Popen(shell=True) calls in cleanup() use f-string interpolation with self._container_id. While the container ID is Docker-daemon-generated (low injection risk), the pattern is the same root cause as the fixed #1241. Using list-form subprocess eliminates the risk entirely.

Suggested fix:

subprocess.Popen(
    [self._docker_exe, "stop", self._container_id],
    stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
    start_new_session=True,
)

Risk Assessment

Aspect Detail
Severity Medium (hardening)
Context These are defense-in-depth improvements, not actively exploitable vulnerabilities
Impact Reduces blast radius of container compromise

Found during a community security review. We use Hermes Agent in production and wanted to contribute back.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/dockerDocker image, Compose, packagingbackend/dockerDocker container executiontype/securitySecurity vulnerability or hardening

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions