Files
infra/modules/nixos/security/README-ai-worker.md
Hermes 993b9c559c fix: restrict docker commands for ai-worker (wrapper blacklist)
SECURITY CHANGE: Keep ai-worker in docker group but block dangerous
docker subcommands via a wrapper script.

Approach:
- docker group membership preserved (ps, start, stop, compose still work)
- Docker binary wrapped with a script that blocks dangerous subcommands
- BLOCKED: exec, cp, commit, diff, export, import, load, save, attach, push, tag
- ALLOWED: ps, images, inspect, logs, start, stop, restart, rm, rmi,
  pull, build, run, compose, system, network ls, volume ls

The wrapper is installed in both system packages and ai-worker's
personal profile to ensure it takes precedence over the real docker.
This is effective for the LLM agent threat model — the agent uses CLI
commands and blocked subcommands simply return an error.

Files modified:
- users/ai-worker.nix — restored docker group, kept sudo audit rules
- modules/nixos/security/ai-worker-restricted.nix — added docker wrapper
  script with blacklist logic and NixOS module integration
- modules/nixos/security/README-ai-worker.md — documentation update
2026-05-20 20:42:32 -04:00

4.3 KiB

AI Worker Restricted Access

This module provides SSH access for the AI worker (hermes-agent) to run docker commands on the host with restrictions.

Security Model

Overview

The ai-worker user is a member of the docker group, but the docker binary is wrapped with a script that blocks dangerous subcommands while allowing safe operations.

Blocked Commands

These commands are intercepted by the docker wrapper and rejected:

Command Risk Reason
docker exec Execute arbitrary commands inside running containers FILE MODIFICATION
docker cp Copy files between containers and host FILE ACCESS
docker commit Create images from running containers DATA EXFIL
docker diff Inspect filesystem changes INFO LEAK
docker export Export container filesystem as tar archive DATA EXFIL
docker import Import a tar archive to create filesystem FILE INJECTION
docker load Load images from tar archive FILE INJECTION
docker save Save images to tar archive DATA EXFIL
docker attach Attach to running container's stdio INTERACTIVE ACCESS
docker push Push images to remote registries DATA EXFIL
docker tag Tag/rename images DATA EXFIL

Also blocked in compose context: docker compose exec, docker compose cp, etc.

Allowed Commands

These commands work normally:

  • docker ps — list containers
  • docker images — list images
  • docker inspect — inspect containers/images
  • docker logs — view container logs
  • docker start — start a stopped container
  • docker stop — stop a running container
  • docker restart — restart a container
  • docker rm — remove a stopped container
  • docker rmi — remove an image
  • docker pull — pull an image
  • docker build — build an image
  • docker run — create and start a container
  • docker compose — compose orchestration (but not compose exec)
  • docker system — disk management
  • docker network ls — list networks
  • docker volume ls — list volumes

How It Works

  1. A wrapper script intercepts docker calls in the user's PATH
  2. It parses the first non-flag argument to determine the subcommand
  3. If the subcommand is in the blocklist, it prints an error and exits
  4. Otherwise, it passes through to the real Docker binary

The wrapper is installed both as a system package and in ai-worker's personal profile to ensure it takes precedence over the real docker binary.

Why Not Use Docker Authorization Plugins?

Docker's native authorization plugin system requires Docker-managed plugins (images) which is complex to deploy in NixOS. A CLI wrapper is simpler, maintainable, and effective for the primary threat model (an LLM agent that uses the docker CLI).

Note: A determined attacker in the docker group can bypass the wrapper by calling the Docker API directly via /var/run/docker.sock. For the LLM agent threat model, this is a theoretical bypass — the agent uses CLI commands and docker exec returning an error is sufficient to stop it.

Filesystem Access

  • Home directory: /home/ai-worker (standard user home)
  • No bind mounts: Cannot access /home/gortium/infra or other host files
  • Cannot access: Any files outside standard system paths

SSH Access

Connect as:

ssh ai-worker@lazyworkhorse

The working directory will be /home/ai-worker. No infra repo access.

Verification

# Verify wrapper is in PATH
sudo -u ai-worker which docker
# Should show: /home/ai-worker/.nix-profile/bin/docker (wrapped version)

# Test blocked command (should fail)
sudo -u ai-worker docker exec ollama ollama list
# Expected: ERROR: docker 'exec' is blocked by security policy

# Test allowed command (should work)
sudo -u ai-worker docker ps
# Expected: CONTAINER ID   IMAGE   ...

# Verify docker group membership
groups ai-worker
# Should show: ai-worker docker

Troubleshooting

If docker commands fail unexpectedly:

# Check which docker binary is being used
which docker
# If this shows /run/current-system/sw/bin/docker, the wrapper is not in PATH

# Check if the wrapper is installed
ls -la $(which docker)

# Verify you're running as the right user
whoami

If SSH connection fails:

# Check SSH key is authorized
cat /home/ai-worker/.ssh/authorized_keys

# Check SSH service
systemctl status sshd