---
description: >-
  Security considerations and design options for isolating Watcher from an untrusted development container.
---

> Part of the Watcher docs. Index of all pages, with summaries: https://watcher-docs.apolloresearch.ai/llms.txt
> Before upgrading Watcher, read the release pages and full changelogs for every version crossed: https://watcher-docs.apolloresearch.ai/releases/index.md
> Found an issue with this page? Report it: https://github.com/ApolloResearch/watcher-bin/issues/new?title=Docs%20feedback%3A%20Hardening%20dev%20containers&body=Page%3A%20Hardening%20dev%20containers%0AURL%3A%20https%3A%2F%2Fwatcher-docs.apolloresearch.ai%2Fclient%2Fdevcontainer-hardening%2F%0A%0A

# Hardening dev containers

The standard [dev container example](devcontainer.md) is for a cooperative
development environment. Watcher and the coding agent run as the same user. The
container can read the host's Watcher sign-in. A process in the workspace can
stop Watcher, edit the agent hooks, read the shared credentials, or call the
local Watcher API.

Do not use that example as a security boundary against code running in the
workspace. If the workspace is untrusted, design the boundary around your
container platform, agent configuration, and authentication requirements.

## Choose the boundary first

Decide which components are trusted before adding container controls:

- The Docker host controls the whole deployment. Anyone who can change the image
  or Compose definition also controls the whole deployment.
- Repository code controls dev container lifecycle commands. This applies unless
  those files are protected by policy outside the repository.
- Agent hook input comes from the workspace. Treat it as untrusted.
- A developer can always start a different, unmonitored agent. This applies
  unless launch is controlled outside the workspace.

Container hardening can restrict an unprivileged workspace process. It cannot
protect against the Docker host. It cannot protect against the image builder. It
cannot protect against the repository administrator.

## Design options

You can combine the following controls into a stronger deployment. They are
design guidance. They are not a copyable hardened template.

| Concern | Possible control | Remaining limitation |
| --- | --- | --- |
| Watcher credentials and state | Run Watcher in a separate sidecar. Give only that sidecar its credentials and state volume. | The container host can still inspect both containers. |
| Hook integrity | Install root-owned managed hooks in the image. Enable each agent's managed-hooks-only setting. | The deployment must pin agent versions that enforce those settings. Test those versions. |
| Process isolation | Use separate PID and network namespaces. Drop Linux capabilities. Remove passwordless sudo. Do not mount a container-runtime socket. | Both containers still depend on the host kernel and configuration. |
| Communication with Watcher | Expose a narrow Unix socket that accepts only known hook events. Do not expose the full local API. | The relay becomes security-sensitive code. It needs its own validation and resource limits. |
| Transcript access | Pass bounded snapshots for the current hook. Do not mount the repository or agent home into the Watcher sidecar. | Snapshot selection must reject symlinks. It must reject path escapes, oversized input, and unexpected file types. |
| Availability | Check Watcher and relay health. Restart failed services. Decide which permission hooks should fail closed during an outage. | Lifecycle events can still be missing during an extended outage. |
| Artifact integrity | Pin Watcher and agent versions. Verify downloaded checksums. Make protected image paths read-only. | Anyone allowed to rebuild or replace the image remains trusted. |

## Runtime reliability

The standard example checks that Watcher starts. Then it leaves Watcher running
in the background. A deployment that needs stronger runtime guarantees can:

- supervise the Watcher process and restart it after repeated health failures;
- check authentication separately, then warn or block according to local policy;
  and
- reinstall hooks after agent changes and verify that a real session reaches the
  Analyzer.

Failing closed improves monitoring coverage. However, it turns a Watcher outage
into a development outage.

## Authentication

Do not pass the desktop credential directory into an untrusted workspace. A
sidecar can use a separate browser sign-in or its own `watcher login`. An
unattended deployment can use an organization API key with only the permissions
it needs (see [Signing in without a browser](headless-sign-in.md)). Keep either
form of authentication out of the workspace container.

Reusing the desktop sign-in is appropriate for the standard example. The example
assumes the workspace is trusted and keeps setup small. It is not compatible
with a boundary that prevents workspace processes from reading Watcher
credentials.

## Validation

Test the finished deployment against its threat model. At minimum, verify that
the workspace cannot do the following:

- read Watcher credentials or state;
- replace or disable managed hooks;
- signal the Watcher process or reach its control API;
- modify the relay or its socket directory;
- mount the Docker or containerd socket; or
- make permission-bearing hooks continue silently when Watcher is unavailable.

Also run an agent turn and confirm the session reaches the
[Analyzer](../concepts/analyzer.md). Isolation checks do not prove that
authentication works. They do not prove that hook discovery works. They do not
prove that upload works.
