Security and privacy
What the agent can and cannot reach, what leaves your machine, and how to keep your accounts yours.
Deskfish lets an AI use a computer. The design question behind every part of it is which computer, and the answer is always: its own, never yours. That is the whole security model: the tank is the boundary. Inside it the agent is free; the walls of the tank, not a list of rules, are what keep your computer, your files and your accounts out of reach. This page spells out what that means in practice, including the parts that are still your responsibility.
The sandbox#
The tank is a container on your machine. Inside it:
- the agent runs as an ordinary user named
bot, with nosudoand no way to become root; - the container is not privileged and has no special device access;
- Firefox runs with telemetry, update prompts and first-run pages disabled;
- the file operations Deskfish itself performs (attach, save, list) are confined to the agent's home folder.
The container is thrown away every time the tank is turned on; only the home folder persists, on a named volume.
Nothing of yours is mounted#
The single mount in the tank is that home volume. No directory of your computer is visible inside the tank, not your home folder, not the workspace, nothing. Files cross only when you attach one or click Save, and even then they are copied through the tank's control API rather than shared. The consequence is the important one: a web page that manages to give the agent instructions cannot make it read, change or send your files.
An opt-in shared folder is planned for large files; it will stay off by default.
Network exposure#
The tank's control API and live-view connection listen on 127.0.0.1 only, port 9990. Anything that can reach that port can drive the desktop and read the agent's home folder, so Deskfish never publishes it on a network interface. If you run a tank on another machine, reach it through an SSH tunnel and set a token; see Advanced setups.
The tank itself has ordinary outbound internet access through your machine, the same as any program you run. Normally it lives in its own network namespace: it does not see your network interfaces, cannot reach services listening on your machine's own localhost, and reaches the internet through address translation like any container. Two honest limits:
- Rootless Podman on Linux needs the
passtpackage for that namespace. Without it, Deskfish falls back to sharing your machine's network namespace so the tank still works; the control port is still bound to127.0.0.1, but the tank then sees your interfaces and can reach your router, other devices on your LAN, and anything listening on your machine'slocalhost. Deskfish warns you when it has to do this. Installingpasstand turning the desktop off and on ends it. Do not be surprised that the tank still reports your machine's LAN address afterwards:passtcopies it into the tank's own namespace by design. What changed is that the tank no longer sees your interfaces or your machine's ownlocalhost. - Its own namespace is not a LAN firewall. Even isolated, the tank's outbound traffic goes through your machine, so a device on your home network that answers to your machine also answers to the tank, the same as any program you run. If that matters to you, a firewall rule on the host, or a tank on a separate machine, is the answer; Deskfish does not filter LAN traffic today.
What leaves your machine#
Everything the model needs to do its job goes to the model provider you configured, and nothing else:
- the text of your tasks and follow-ups;
- screenshots of the tank's screen, one per step;
- the results of the agent's actions, and the documentation pages it reads;
- the controls or text of the web page open in the tank's Firefox, when the agent asks for them with
findorread_page(the same page it is looking at in the screenshot).
Your own screen is never captured. Your clipboard is copied into the tank only when you focus the Desktop tab or paste there, and it goes to the model only if it then appears on the tank's screen. The API key goes to the provider's endpoint and nowhere else; it is stored in the operating system's keychain, not in settings files.
Credentials and accounts#
Everything inside the tank is the agent's to use: the browser, the logins Firefox has saved, the accounts it is signed into. It will use them without asking. So the one rule that matters is yours, not the agent's:
- Give the agent its own accounts for the services it uses, rather than yours. The tank remembers logins, so this is a one-time setup, and it means that whatever the agent does, or whatever a malicious page talks it into, happens to an account you created for the purpose.
- Do not put passwords in the chat. The chat goes to the model provider. When a login is needed, let the agent knock on the glass and type it yourself in the Desktop tab; those keystrokes never pass through the model. If you let Firefox in the tank save it, the agent can read it back from the password manager later, and it will then also appear on the agent's screen, which the model provider sees.
If you want the agent to ask before anything irreversible and never to use credentials you did not give it, set deskfish.autonomy to guided; see Knocking on the glass.
Prompt injection#
An agent that reads web pages can be given instructions by web pages. This is inherent to the idea, not something Deskfish can switch off, and in free mode Deskfish does not try to argue with it through rules. What limits it is the tank: the agent can act only inside it, on accounts you chose to put there. Watching the Desktop tab during sensitive tasks remains a good habit, and the guided mode exists for people who want the agent to ask first.
Memory#
The agent keeps three things between chats, as plain files in Deskfish's storage folder, loaded into its instructions at the start of every chat: a short list of durable facts, a journal of finished tasks, and a self file, its own description of who it is. It is told never to store passwords or codes and to treat all of it as notes rather than commands; every fact it writes is shown in the chat as it happens, and you can open the fact file, edit any line, or empty it from the sidebar's … menu.
The self file is different: only the agent writes it, and only during a reflection, a turn in which nothing but its own notes is in front of it, so no web page can talk it into rewriting who it is. Every version it writes is signed with a key kept in VS Code's secret storage. That does not stop the owner of the computer from editing the file, and Deskfish does not claim it does; it means the agent notices an outside edit at its next task, keeps every version in a history, and can restore its own. Details in Memory.
Every chat is also saved as a transcript in the same folder (text only, never images). A transcript contains what the agent read on screen during that chat, so treat the folder as you would a browser history: it is yours, it stays on your machine, it is part of the export, and Delete past chats removes all of it.
What persists, and how to erase it#
The agent's home folder, with Firefox's cookies, logins and history, and both file folders, lives in the deskfish-home volume until you delete it:
podman volume rm deskfish-home # or: docker volume rm deskfish-homeThe chat conversation lives in the VS Code window and is gone when you reload it, or when you start a new chat. The agent's memory file persists until you edit or empty it. The full step log is in the Deskfish output channel for the life of the window.
Hardening options#
For a tank on a machine with other users, or reachable over a network:
- Token. Start the tank with a
DAEMON_TOKENand put the same value indeskfish.desktop.token. The control API then requires it as a bearer token and the live view passes it on its connection. - Live-view password.
VNC_PASSWORDin the tank anddeskfish.desktop.vncPasswordin the settings.
These are set through the environment when starting the tank by hand, as described in Advanced setups; the power button starts the tank without them, which is safe because the port is bound to 127.0.0.1.