Security

What runs where, and who can reach it.

antgrid runs your coding agents on your own machines and carries your traffic to your phone through a relay that holds no key to it. This page is the architecture, not a set of assurances — every claim below is one you can check in the public repository, and every claim that has a limit is printed next to it.

If you are evaluating this for a work machine, the three sections that matter are what the relay sees, what has to be true before a phone can drive a machine, and what doesn't exist yet. Nothing here is a compliance statement.

The wire

The relay forwards bytes it holds no key for.

Traffic between your devices and your machines is end-to-end encrypted. Keys are made on the two devices, and the relay is never given one.

app ⇄ machine · handshakemutual auth
  1. 1 Both sides generate an ephemeral X25519 keypair, fresh for this connection, and exchange the public halves.
  2. 2 Both sign a canonical transcript with their long-term Ed25519 identity key. The transcript binds both device identities, both ephemeral public keys, a 32-byte fresh nonce, the machine binding and the protocol version.
  3. 3 Each side verifies the other's signature against the key it already holds for that device. A key exchange someone tampered with in transit produces no signature that verifies.
  4. 4 Both sides check an HMAC key-confirmation tag, compared in constant time. No application data is sent or accepted before that passes.
  5. 5 Transport is AES-256-GCM, with a separate key for each direction.

Because the session keys are ephemeral, a long-term signing key stolen later does not decrypt sessions that already happened. Session keys live in memory for the life of one connection, are never written to disk, and every teardown path overwrites their buffers.

Limit

That overwrite is best effort. Both implementations run in garbage-collected runtimes, so residual key material in a process dump is expected and is not treated as a vulnerability.

Scope

This covers app-to-machine traffic that crosses the network. The desktop app driving the machine it is running on does not use this channel at all: it talks to its own bridge over a loopback socket on 127.0.0.1, authenticated by a per-process token compared in constant time. That traffic never leaves the machine. The file carrying that token is written owner-only on POSIX, as are the machine's device inventory, its phone list, its remote-access switch and its session records.

ephemeral X25519 per connectionEd25519 transcript signaturesAES-256-GCM, one key per directionconstant-time key confirmation

The relay

What the relay does see.

Zero-knowledge is a claim about content, and only about content. Everything the relay needs in cleartext to admit a socket and route a frame, it has. Here is that list in full, beside the list of what it never holds.

in cleartext at the relaymetadata
  • Your account idtaken from the verified token — it is the routing key
  • Device idsone per machine, one per app slot
  • The device name in the hello frameon a machine this defaults to its OS hostname
  • Each device's Ed25519 public keyand its connection epoch
  • The licence credential id presentedkept so a revocation can find the socket
  • Your IP addressin memory only, for per-IP connection caps and rate limits
  • The Host header of the upgraderebuilt into the signature body so a hello cannot be replayed elsewhere
  • The hello timestamp and noncefor replay rejection and equal-epoch arbitration
  • Connect time and last-seen timeper open connection
  • Who is sending to whomthe destination in each frame's cleartext route header
  • Which channel a frame is oncontrol or preview — it keys the rate-limit bucket
  • The size and timing of every frameand its kind byte, forwarded without interpretation
  • Which of your devices are onlineand it tells your other live connections
  • Push routingthe destination token and provider transit the relay
  • Device ids in operational logsa ping timeout names the device it dropped
never at the relayciphertext
  • Message payloadssealed on the sending device
  • The stream envelope inside themincluding stream ids
  • Project names and project ids
  • File paths and file contents
  • Terminal output
  • Your prompts and the agent's replies
  • The text of a push notificationit forwards a sealed blob and a placeholder
no database, no file, no queue anywhere in the relay — an entry exists only while a socket is open

Routing

The relay routes only between devices that belong to the same account, and that check runs fresh on every frame. It is the only routing authorization there is. A blocked route and an offline device get the identical answer, so the relay cannot be used to discover which of your machines are up, and presence is announced only to other live connections on your own account.

Admission

Every connection is admitted by a single signed hello frame, verified in a fixed order: schema, clock window, Ed25519 signature over a body that binds the relay hostname, replay cache, licence, then connection arbitration. Nothing is queued for a device that is not connected — a frame addressed to one is refused and dropped.

Push notifications

The notification body is sealed to your phone's own key on the machine — ephemeral X25519, HKDF, AES-256-GCM — before it ever reaches the relay, and the relay hands Apple or Google a generic placeholder that your phone replaces once it decrypts. Apple and Google see delivery metadata and an opaque blob. The destination push token and provider do transit the relay, which is why they are in the list above.

What we are still trusted with

This design takes the relay out of the trust boundary. It does not take our account service out of it. A relay operator who tampers with the key exchange cannot produce a signature your device accepts — but your phone learns a machine's Ed25519 identity key from your account's device inventory, served by app.antgrid.ai, so a compromised account service could hand a device that has not yet cached the real key one of its choosing. The relay is not trusted with identity. The account service is.

Remote access

Three things have to be true before a phone can drive a machine.

They are independent and they are checked together. Any one of them false and the command does not run.

01

The device is on your signed-in account.

A device is admitted from your account's own inventory — there is no pairing code or QR ceremony to intercept — and its Ed25519 identity must verify against the handshake transcript before anything proceeds.

02

That machine's remote-access switch is on.

Off on a fresh install. One boolean for the whole machine, read live at every check, so turning it off takes effect immediately without restarting anything.

03

The project is one that machine already knows.

A shape check plus a lookup in that machine's own catalog of projects bounds which project a remote device is allowed to name.

With the switch off, a remote device sees nothing: every inbound verb is dropped at a single chokepoint, the preview and HTTP tunnel is gated separately because it bypasses that path, and outbound streaming stops at the send.

Not per-project permissions

The switch is machine-wide. The project catalog is a bound on what a remote device may name, not a grant you issue per project.

A known device is identity, not permission

The machine's phone list holds labels, push routing and last-seen. Removing a phone from it revokes nothing. Revocation is deleting the device on your account — which closes its live relay sockets immediately — or turning the machine's switch off.

The desktop is exempt by design

The app driving its own machine goes over the loopback socket and never depends on the relay, so it keeps working with the switch off.

Your agents

Your agents talk to their providers, not to us.

Coding agents run on your machine as ordinary local processes, launched from your own environment, and reach their model providers directly under your own logins. antgrid operates no model endpoint and holds no model-provider credentials — there is no provider API key anywhere in the bridge, the relay or the web service.

That is not the same sentence as "your code never leaves your machine", and we are not going to write that one. Your agent sends your code to its provider; that is what it is for. The claim is that antgrid adds no hop of its own and no key of its own.

Handler runs your agent again

When you arm Handler on a session, it runs the agent you already picked for that session headlessly and restricted over that working tree — with a proven read-only tool set where the agent offers one, and with the agent's own restricted mode, and no transcript handed to it, where that restriction is configuration rather than a flag we can verify. So working-tree content and transcript excerpts reach the vendor you already chose, on your own account, without a fresh action from you for each call.

It never borrows a different vendor's agent to supervise a session unless you pick one yourself, and those runs are kept out of your own session history.

antgrid does not sandbox your agent

An agent runs with your environment and your permissions, and an agent you have configured to skip approvals will skip them. Handler's destructive-path floor is an advisory floor, not a sandbox.

In an isolated session, the branch's own setup steps run as shell lines — the same trust class as the commands you run yourself. Escapes out of the checkout path are refused, but the commands themselves are branch content.

Honest inventory

What doesn't exist yet.

Every item here is something a reasonable reviewer will ask for and we do not have. None of it is written as a feature.

No second factor.

Sign-in is single factor: an emailed magic link, GitHub, Google, or email and password. There is no TOTP, no passkey and no hardware-key support. The primary path is the magic link, which has no password to steal, and a password set on an unverified address is dropped as soon as someone proves that address another way.

No audit, no penetration test, no certification.

What exists is a published protocol specification, cross-language test vectors that both implementations must pass, and a security policy. None of those is an external review, and we are not going to describe them as one. We hold no SOC 2 report and no ISO certification, and this page makes no compliance claim of any kind.

Telemetry is on by default.

It is opt-out, in app settings. Events carry no account id, no device id and no content — an event name, your platform, the app version, and a random install-scoped id that goes only to our own backend and never to the analytics host. Switching it off stops new events and discards anything still queued; crash reporting follows the same toggle and picks the change up at the next launch.

Crash reports are scrubbed on the device, not on receipt.

File paths are redacted throughout a report before it is sent, and raw source lines and local variables are dropped rather than redacted. That is a scrubber, and a scrubber is a best effort against a stack trace it has not seen before.

Denial of service is out of scope.

There is per-IP and per-channel rate limiting, but it protects the relay, not your availability. A rate-limited frame is dropped unrecoverably and only the sender is told. Do not read it as an uptime guarantee.

A machine that is already compromised is out of scope.

Physical access, a malicious local user, and an attacker who already has your shell are all outside what the bridge defends against. That user already has everything your agent has.

What we collect, and for how long, is set out on the privacy page.

Verify it

Check the crypto claims yourself.

The handshake is specified in public down to the byte layout of the signed transcript, with cross-language test vectors that both the TypeScript and the Dart implementation must pass. The wire protocol and client-side encryption are MPL-2.0 and carry their own licence files.

Antgrid's first-party distributed code is MPL-2.0, except the relay and web services, which remain Elastic-2.0. MPL applies to covered files, not to code you use Antgrid to work on.

Disclosure

Reporting a vulnerability.

If you can read traffic the relay is not supposed to read, or run something on a machine without its owner's account and consent, we want to hear about it before anyone else does. Please don't open a public issue, discussion or pull request for it.

Email

contact@radhaai.com

Put "Security" in the subject line.

GitHub private advisory

Report a vulnerability

Preferred, and it keeps the thread on the repository.

We acknowledge reports within three business days, tell you what we found, keep you updated while we fix it, and credit you in the release notes if you want it. We ask for a reasonable window before public disclosure. Please test against your own account and your own machines.

What is in scope and what is not is listed in SECURITY.md. Machine-readable contact details are at /.well-known/security.txt.