# 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: ```bash ssh ai-worker@lazyworkhorse ``` The working directory will be `/home/ai-worker`. No infra repo access. ## Verification ```bash # 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: ```bash # 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: ```bash # Check SSH key is authorized cat /home/ai-worker/.ssh/authorized_keys # Check SSH service systemctl status sshd ```