Security
What is encrypted, with what, where the key lives, what is sandboxed, and the boundary of all of it, stated plainly.
Where your work runs
The agent runs in a Docker container on your own computer. The cloud never runs your code and never stores your API keys in a form it can read.
Task execution, containers, terminals and scripts run only on your desktop. The cloud service at board.boragosoft.com stores synced board data and relays requests to your desktop over an outbound tunnel the desktop opens. It has no Docker, no runner and no model credential. With cloud sync off, which is the default, the app itself sends your work nowhere but the AI provider you configured and the git remote you set. Beyond that the app checks for updates, downloads the dictation model once, downloads Docker and gVisor when you ask it to set them up, pulls a base image when a project container is built, reads a provider's public status page after a failed run, and sends a diagnostics report only when you press Report a problem. What the agent's own commands send is decided by the task. The agent has the container's network, so a task that deploys, pushes or calls a service does exactly that.
Credentials
API keys, environment variables, git keys and vault keys are encrypted with AES-256-GCM. On your desktop the key is sealed by your operating system's keychain, where there is one. In the cloud the key is wrapped under your password. A copy of the cloud database is a blob without it.
Secrets at rest use AES-256-GCM with a fresh nonce for every value. The desktop's key is device-local, sealed by the operating system's credential store: the macOS Keychain, Windows DPAPI, or a Linux Secret Service such as gnome-keyring or KWallet. On a Linux session with no such store the key is written unprotected and the app says so, once per launch and beside the cloud sign-in in Settings. When the desktop is signed in to cloud sync, secrets are encrypted under the account's data key, which is itself wrapped under a key derived from your password. The cloud stores the wrapped key and a hash of the password, never the password and never the data key. At sign-in your password reaches the cloud over TLS, is checked, and is used once, in memory, to open the data key and hand it to your desktop in the sign-in response. Nothing from that moment is kept. A one-time recovery code, shown once when you enrol, covers a forgotten password.
Secrets are written only by the desktop. A project secret or an environment variable set from the browser or phone is relayed to the desktop, which encrypts it. A vault key or a self-hosted service key can only be entered on the desktop. The app refuses to store a credential in plaintext. On Linux it detects a weak or absent keyring and warns once per launch. A journal beside the database keeps a secret's recent values, so an accidental overwrite on that machine is recoverable.
Containers
Each project has its own container and, once one created on an older version has been moved there, its own network. On Linux with gVisor installed, the container runs under it. Ports stay on localhost unless you open them.
Per-project Docker containers on per-project bridge networks, once a project created on an older version has been moved onto its own. On Linux with gVisor installed, containers use its runtime, a user-space kernel that intercepts system calls. On macOS and Windows, Docker Desktop's virtual machine isolates the host and gVisor is not used. Published ports bind to 127.0.0.1 unless a port is marked for the LAN. When container management is enabled, the agent reaches Docker only through a policy proxy that permits the sibling containers the agent created on the project's network and refuses everything else. Containers carry a memory cap derived from the host. Restart and rebuild ask for a confirmation because they discard uncommitted work in a container-only workspace.
Accounts
Passwords are stored only as hashes. Sessions last 30 days and renew while you use them. Two-factor authentication with an authenticator app. One desktop per account.
Passwords are stored only as hashes. A session lasts 30 days and renews itself while you use it. A client offline for more than two weeks may need to sign in again. Two-factor authentication uses time-based codes with hashed recovery codes. Losing the authenticator has a password-gated recovery path with a 24-hour hold and an alert with a cancel link sent to the primary email. Deleting the account at once needs the password and a second factor. Each account links exactly one desktop installation. A second desktop must confirm a takeover, after which the previous one is refused. Credential changes send a security notice. A desktop sign-in can be approved from a phone that is already signed in, so the password need not be typed on the desktop.
The web client
No cookies and no trackers on the website. The board client is served with a Content Security Policy and Subresource Integrity.
The website sets no cookies and loads no third-party scripts. The board client at board.boragosoft.com carries a Content Security Policy and Subresource Integrity on its assets. The board uses browser local storage for per-device preferences only.
The cloud
Encrypted disks, encrypted backups, TLS everywhere.
The database sits on an encrypted volume. Nightly backups are encrypted at rest. Attachments sit in a storage bucket with server-side encryption switched on. Every connection uses TLS. The sync routes and the desktop tunnel accept only the account's linked desktop.
What is not end-to-end encrypted
Your task text, comments, chat, notes and run output are stored readable on the cloud so your phone can read them while your desktop is off. They are protected by disk encryption, encrypted backups and TLS, not by your password. Keep cloud sync off and they never reach the cloud.
Task titles and descriptions, comments, chat messages, notes, notifications and run output are stored as readable rows on both the desktop and the cloud. The cloud must read them to serve the browser and the phone and to merge edits made on two devices. They are protected in transit by TLS and at rest by volume and backup encryption, not by the account's data key. If your work must never reach the cloud, leave cloud sync disabled, which is the default, or use the browser on your own network instead.
The output of a run is scrubbed of the credentials the run was given before it is
stored or shown, each replaced by [redacted:NAME]. The model itself still
sees whatever a command prints during the run, a very short value is left as it is, and
a value the agent transforms first is not recognised, so a task should still never ask
for a secret to be printed.
What the cloud can and cannot read
Credentials are ciphertext the cloud cannot open. Board content is readable, so your phone can show it.
| Data | Stored on the cloud as | Why |
|---|---|---|
| Project API keys, environment variables, git keys and tokens, vault keys, self-hosted service tokens | Ciphertext under the account data key | The cloud stores neither the password nor the unwrapped key. It sees both only in memory, at sign-in, when the password is set, changed or reset, and when a new recovery code is issued, so a copy of the database is inert for these columns |
| The two-factor secret | Ciphertext under a key the cloud service holds | The cloud checks your authenticator code at sign-in, so it must be able to read this one. Recovery codes are stored only as hashes |
| The wrapped data key | A blob that needs the password or the recovery code | This is what makes a database dump inert |
| Task titles, descriptions, comments, chat messages, notes, notifications, run output, flow definitions | Readable rows | The browser and the phone must read them with the desktop off, and the cloud merges edits made on two devices. They are protected by the volume encryption, the backup encryption and TLS, not by the account key |
| Attachments (Pro, Max and the trial) | Readable objects in an object store | Same reason |
| Environment variables flagged device-local | Not stored on the cloud at all | The flag keeps the value on the one machine |
| Environment variables flagged write-only | Ciphertext, and never returned by any read after being set | The flag governs what leaves the server, not what the container receives |
A key typed on the desktop is encrypted there and synced as ciphertext. A project secret or environment variable typed on the browser or the phone is relayed to the desktop over TLS and encrypted there. The cloud does not store it on the way. At use, the desktop decrypts a secret and hands it to the container's process at the moment a shell, a run, a script or a flow starts. It is never written into a Docker file, the task text or the prompt.
Known residuals
- Browser access on your local network is login-free by design and broadens the attack surface on that network. Off by default.
- A secret set from the browser or phone passes through the cloud in memory, over TLS, before the desktop encrypts it.
- At sign-in, whenever the password is set, changed or reset, and when a new recovery code is issued, the cloud holds your password and the opened data key in memory for that request. It stores neither, and hands the key only to your linked desktop.
- The git credential is present in the container's environment during a run, so the agent can use it. That is its purpose and its exposure.
Reporting a vulnerability
Write to security@boragosoft.com. The disclosure details are at /.well-known/security.txt.
Related: Security and recovery features, Cloud, browser and phone, Privacy, Security, in an assistant's words.