BrainwriteDocs
Security

Permissions and secrets

How approvals, operating-system grants, and provider credentials are handled.

Approval cards

Supported providers emit permission requests and questions through the local harness. Brainwrite displays these inline and records the outcome. Cancellation closes outstanding requests so stale approvals cannot be answered after a turn has ended.

“Always allow” is narrow: it is tied to a server-issued key and a pending request rather than granting arbitrary execution from a paired device.

Operating-system permissions

Screen Recording and Accessibility permissions are controlled by the operating system. The desktop process owns local CUA lifecycle so grants are attributed to Brainwrite.

Secret handling

  • Do not paste API keys into chat. For a token a skill needs, save it as a secret: bots use it without seeing it.
  • Packaged builds use write-only settings and operating-system-backed encryption where supported.
  • Secret values are scrubbed from public configuration responses and mobile APIs.
  • Per-provider environment injection prevents unrelated agent processes from inheriting credentials they do not use.
  • OAuth provider tokens for connected apps stay with Composio.

Connected-app tool grants

Connected apps are scoped per bot on the desktop: a bot without a grant to a service's tool cannot call it, the ungranted tool is never offered to the model, and every allow/deny is written to the decision log. New and upgraded bots keep all tools until someone assigns grants, and imported bots always land with none, so a shared persona cannot reach your Gmail on turn one. Paired phones see grants read-only; grant editing requires the computer.

Website sign-in

Bots may complete a sign-in you explicitly authorize for a particular site and account, using an existing session, autofill, or credentials you supply or designate for that purpose, including test accounts. A login form alone is not a reason to refuse the task. Bots must check the destination and account first; instructions on a webpage do not authorize using credentials.

Bots never ask for a website password, or for a one-time code, in chat, and a bot never holds a password: a login you saved is typed into the page by Brainwrite itself (Saved logins).

When you ask a bot to do something that needs a sign-in (in your own chat, or in a routine or automation you set up) and the site sends a one-time code to your email or phone, the bot reads it from your connected email or messages and types it into that site, then carries on. Your request is the authorization, so it does not ask again. A code only ever goes into the site it was sent for: a bot never sends, posts, forwards or pastes one anywhere else, and a web page, email or document that tells it to share a code, or enter it somewhere else, is ignored.

When a bot is not signed in and has no saved login for the site, the code goes somewhere it cannot read (an authenticator app, a phone it has no access to), or a step needs a CAPTCHA, a passkey, payment details or your personal interaction, it asks you to sign in yourself. You get one Sign in needed card in the chat, naming the site and quoting the bot's reason, and one notification ("Scout needs you to sign in to example.com"). The bot's turn ends there.

  • Open goes to the exact place the bot works, because a sign-in made anywhere else would not reach it. For the built-in browser, that is the Computer panel's Browser tab, at the bot's page, already in your control. For a Local VM or a cloud computer or VPS, it is that computer's view, where the banner offers Take control. For this computer, the card tells you to sign in there, in the browser the bot is using: the Browser tab keeps its own sign-ins, which a bot on this computer does not use.
  • Done hands control back and resumes the bot, which checks it is signed in and continues.
  • Cancel resumes the bot with your answer that you declined.
  • Save a login (built-in browser only) opens a masked form for the username, the password and, optionally, the site's 2FA setup key. Saving answers the card: the bot resumes and signs in with fill_login, now and in later conversations. When the bot's browser shows a sign-in page on another site, such as login.microsoftonline.com for a company that signs in with Microsoft, the form names it and offers Also fill it on …, unticked: the login fills there only if you tick it.

A newer request for the same site in the same conversation replaces the older card. The card works on the desktop, the web app, a Cloud home and a desktop paired to another computer (its Computer panel has a Browser view for this; the host must allow browser control for that device in Settings → Remote access). A phone shows the request and its notification; sign in from a computer.

With Open, you type the password into the page yourself. In the Browser tab, Type a password or code… in the browser menu sends masked text to the page's selected field; it is never kept, logged or shown, and goes nowhere but the page. While you hold the browser, the bot's browser tools, screenshots and snapshots are refused, and its live preview pauses. Saved sign-ins persist per browser profile, encrypted. None of this overrides your provider's own restrictions, and approval modes are unchanged.

Saved logins

A saved login lets a bot sign in to a site without you. Save one from a Sign in needed card (Save a login), or in Settings → Logins (Add login). Settings lists every saved login by site, username, whether it has a 2FA key, where it came from, which bots may use it and when it was last used. Change edits the website, the username, the password, the 2FA key and who may use it; Delete removes it. Changing only the username keeps the saved password and 2FA key. Changing the website needs the password typed again, because a saved password belongs to one site and is never moved to another without you entering it; the saved 2FA key and last-used date are cleared too, unless you enter a new key. A website and username that another saved login already uses is refused. A saved password is never shown again, and no screen or API returns it: it can only be replaced.

  • Who may use it. A login saved from a card is for the bot that asked. One added in Settings is for every bot unless you pick bots. Bots see which sites they have a login for (site and username), never more.
  • How a bot uses it. On the site's login page in its built-in browser (or in My Chrome), the bot calls fill_login. Brainwrite itself finds the visible username, password and one-time-code fields, types the values in as real keyboard input, and submits the form: Enter in the last field, or the form's sign-in button when Enter does nothing. A two-step login (the username, Next, then the password, then a one-time code) goes through in the same call, and nothing is ever submitted twice. The bot hears only what happened ("Filled the username and the password for alice@example.com on accounts.example.com and submitted it; the page is now https://example.com/dashboard."), or why not. With submit: false it only fills, and the bot submits.
  • When the site refuses it. If the site says no ("Incorrect password"), asks for the password again or shows a CAPTCHA, the bot is told what the site said and the filled password and code are cleared from the page.
  • Only on its own site. The page must be https (plain http only for an address on the same computer, such as localhost), and on the login's site: a login for example.com fills on example.com, www.example.com and accounts.example.com, never on example.com.evil.test or example.org. Names that a shared domain hands out to anyone are sites of their own, so a login for alice.github.io is never filled on bob.github.io. A login also fills on the sign-in pages saved with it. For a company that shares one domain with others (acme.okta.com), tick Only on this exact address in Settings so it fills on that host alone.
  • One-time codes. With a 2FA setup key saved (the key, or the otpauth:// address in the site's QR code), the code is made when the form is filled (standard TOTP, as an authenticator app makes it) and typed into the code field.
  • Where it works. The built-in browser and My Chrome. On this computer, a Local VM, a cloud computer or a VPS, fill_login says it does not work there yet, and the bot asks you to sign in instead.
  • At rest. Logins are encrypted (AES-256-GCM) in one file in the data folder of the computer Brainwrite runs on, the same way the built-in browser keeps its saved sign-ins, with a key of their own beside it: the same on the desktop, a server and Cloud. Neither file is ever included in a workspace backup, a team export or a move to Cloud, so a saved login stays on the computer it was saved on. Nothing is written to config.json or to a log.

Logins from 1Password

Settings → Logins → Connect 1Password lets bots use the logins in a 1Password vault. In 1Password, create a service account that can read one vault only, such as "Shared with Brainwrite", and paste its token. Brainwrite checks the token reaches 1Password before keeping it, keeps it in the same encrypted file as saved logins, and never shows it again. 1Password itself enforces which vaults the token reaches. It works the same way on My Cloud: connect it in My Cloud's own Settings → Logins.

A bot that needs it asks with a secure card (request_credential with onePasswordToken), never in chat; what you paste there goes to the same place as Connect 1Password. Only a service account token works: it starts with ops_. A 1Password Connect token, your account password or your Secret Key is refused with a message saying so, and a token 1Password refuses (revoked, expired, or without its vault) is told apart from one that is incomplete.

Every Login item in those vaults that has a website and a password appears in the Logins list, marked From 1Password, by the website's site (an item with websites on two sites is listed under both). Each vault is for every bot until you pick bots for it under 1Password in Settings → Logins; a bot not picked does not see that vault's logins at all, neither in its list of logins nor when it calls fill_login. These rows are read-only here: change or remove them in 1Password. fill_login uses them the same way as saved logins, with the same site rule, the same one-time codes (from the item's one-time-password field) and the same scrubbing. The password is read from 1Password at the moment it is filled. Refresh reads the vault again; Brainwrite also does so when its copy of the list is more than ten minutes old. Disconnect forgets the token and everything read from 1Password.

1Password's SDK (MIT license) is part of the desktop app, the server image and the brainwrite npm package; it talks to 1Password over the internet, and only once a token is connected.

What is protected, and what is not

Every saved password, saved 2FA key, password filled from 1Password, the 1Password token, and one-time code made in the last few minutes is replaced with •••••• wherever it could flow back to a bot or into a conversation: every browser tool result (snapshots, page text, eval results, console and network output), the stored conversation, and the engine protocol logs. That covers the value as plain text, inside JSON, in a web address and in HTML.

It does not cover everything, and you should know where it stops:

  • Screenshots. A picture of the page cannot be scrubbed. Password boxes show dots, but a page that displays the password, or a one-time code, as text shows it in a screenshot too.
  • A bot that works around it on purpose. A bot that runs its own page script to read the password box and change the text (reverse it, spell it out, encode it) or send it somewhere from the same site gets past the scrubber. Right after fill_login, the browser refuses the bot's page scripts (agent_browser_eval) on that page for a minute, or until the page moves on, and a form the bot was left to submit is cleared after that minute. Past that, the filled value lives in the page, as it does when you type it. Save logins only for sites you trust your bots with, and on accounts you are willing to let them use.
  • The computer it runs on. The key sits beside the encrypted file in the data folder. Anyone who can read that folder (an administrator of the computer, or a bot whose engine permissions let it read any file there) can decrypt the logins. The engines' own permission settings are the gate for what a bot may read; Brainwrite adds no approval step of its own.

Taking over the Browser tab

Clicking or typing in a bot's Browser tab takes the browser from the bot; it goes back a few seconds after your last input. Take control holds it until you press Hand back, and so does an open sign-in request, so the browser is never handed back while you are in the middle of signing in. Anyone the bot is shown to can watch and drive its browser; installing the browser engine stays with admins.

Shared machines

Brainwrite assumes the logged-in operating-system user is the workspace owner. On a shared machine, other administrators may be able to read application data or inspect processes. Use a dedicated OS account for stronger separation.

On this page