v0.1.2-alpha.25 is outsee the release →
[ SECURITY ]

The container is the boundary

Agents run as root inside their container with Docker's default capabilities, because dropping them breaks the package installs agents actually do. The security model is what the container is handed: its mounts and the credentials mounted into it.


[ THE CONTAINER ]

What isolates an agent

The container is the boundary

Aether does not build a second sandbox inside it. These stances are documented so they are not re-raised as findings.

agents run as rootby default; a harness may map a run to a non-root user
docker's default capabilitiesare kept, because agents install packages and use sudo
no read-only rootfsand no no-new-privileges, since each one breaks something agents actually do
so treat container rootas able to do anything the container can reach

What the container is handed

The mount policy and the credentials mounted in. That is the whole boundary, and everything else follows from it.

my-server:2222 / the boundary
THE SERVER BOX
MOUNTED INthe run's own git worktreeyour credential homethe pinned profile and tool snapshotsthe run's unix socket
RUN CONTAINERthe agent, running as root by defaultdocker's default capability set, kept deliberatelypackage installs, build tooling and sudothe network this container can see is the network it can reach
/var/lib/aetherthe data directory, owned by the server
Aether does not try to build a second sandbox inside the container, and says so plainly. Every restriction that breaks installs, build tooling or sudo breaks real work, so read container root as capable of anything the container can reach.

Hostile agents

If you run agents you do not trust, put the data directory on a filesystem mounted nosuid,nodev.

the filesystem, not the bindbecause Docker has no per-bind nosuid or nodev controls of its own
without ita root agent can plant a setuid binary through a writable bind mount and have it survive on the host
the docker socketis never mounted into a workspace container, and no mount may nest under the paths Aether reserves
logins are mounted per memberinto that member's runs only, so a run never sees anyone else's credentials
[ THE DASHBOARD ]

No server-side HTTP

The page is served from your machine

aether gui serves the dashboard locally and proxies the API over your own SSH connection to the server. SSH stays the only network surface the server exposes.

127.0.0.1 / the local gateway
YOUR MACHINEaether gui, servingbinds 127.0.0.1, and nothing elseyour own SSH key, in this process
ssh :2222
ssh :2222
THE SERVERaether-server serve --addr :2222no HTTP listener of any kindSSH is the only network surface
BEARER TOKENevery request carries it, loopback included, because HTTP cannot identify a member on its own
32 random bytesone per process, minted at startAuthorization: Beareron every API call?token=on websocket handshakes and the first browser tab
The token dies with the process serving the page. There is nothing to revoke and nothing to expire.

What the gateway does and does not do

The identity is your own SSH key, held by the same process that serves the page.

loopback onlyit binds 127.0.0.1, and there is no flag to expose it
a per-process tokenwith no TTL and nothing to revoke, because it dies with the process
the same authority as the CLIevery call passes the same capability checks a terminal on that machine would
losing steer mid-attachis refused by the server, and the page drops to a read-only mirror
[ COORDINATION ]

When two runs touch one file

The mount is the authentication

Each container gets a unix socket it can message other overlapping runs through. Whoever connects on a run's socket is that run, so no token enters a container.

my-server:2222 / one socket per run
run-014/run/aether/coord2.socksendingrun-015/run/aether/coord2.sockreceivingrun-016/run/aether/coord2.sockidleTHE MOUNT IS THE AUTHENTICATION
UNREAD PER INBOX3 / 100
3coord.status, coord.send, coord.inbox4 KiBper message, rate limited per run8distinct correspondents per run
Messages are rate limited per run and recorded on the workspace timeline, so a conversation between two agents is as attributable as anything else.

Defence in depth, not a boundary

Runs in one workspace already share a repository, so influencing each other through file contents needs no authorization at all.

the overlap is computedfrom the two runs' own diff snapshots, so a wide refactor overlaps everything
a cap bounds it8 distinct correspondents per run, rather than trying to tell a refactor from an attack
the bridge binaryis the server's own, mounted read-only, and carries no credentials
--conflict-coordination=falseturns the whole feature off if that trade is not acceptable

[ NEXT ]

From a bare box to a branch

Server setup, agents, runs, the dashboard, and the branch that comes back.

$ curl -fsSL https://raw.githubusercontent.com/3xDevOps/Aether/main/scripts/install.sh | sh
back to the landing page