Skip to content

Security model

Giving an agent access to production safely calls for a broker: something that holds the credentials, offers the agent a few narrow, intent-level tools, asks a human before anything changes, and records everything. That is what Periskopos is for your assistants:

  • Keys never reach the agent. The MCP server is a thin client of the local server; no tool returns a key or token.
  • Narrow tools. “Redeploy Nova-Shop”, not “here is Render’s API”. An agent can’t add, edit or delete apps or accounts.
  • Writes are off by default, per account (“Allow actions”).
  • The server asks you before any agent acts, whatever the agent’s own settings.
  • Dangerous actions are screen-only: the app’s name must be typed.
  • An audit log records every request and every action, and who started it.

What “safe” means here, from most to least likely:

Threat Covered?
A An agent uses only the MCP tools, but is wrong or prompt-injected and asks for the wrong action Yes: every agent action waits for your approval on screen, unless you set a rule or grant for it
B An agent wanders through files it can read (a repo, the data folder) and uses what it finds Yes: no provider key is in a project folder; the only token on disk can read and ask, not act
C An agent deliberately attacks Periskopos from a shell running as your user Mostly. The easy ways are shut: the page carries no key and is served only to the app’s window, so curl gets nothing; the session key is never on disk, on a command line or in an environment. What’s left needs real effort: reading the app’s memory, or reading the keys file in your profile and calling the providers directly. On one OS account nothing is fully sealed; only a separate OS user would close that
D Something on the network Yes: it listens on 127.0.0.1 only, and checks Host and Origin (DNS rebinding, other sites in your browser)

The honest summary: a boundary against agents that misbehave, not against an attacker who already owns your account.

Two keys, and only the app opens Periskopos

Section titled “Two keys, and only the app opens Periskopos”
  • The app’s session key. The desktop app makes a fresh one each time it starts, writes it to the server’s stdin (never the command line or the environment, which other programs can read), and gives it to its own window as an HttpOnly, in-memory cookie that page scripts can’t read. Full access. Nothing else ever gets it: a browser or curl gets only a page saying Periskopos opens only in its desktop app.
  • The agent token, the token file in the data folder, used by the MCP server. Off until you switch assistants on. While on, it may read anything under the API (nothing there returns a key), check an app now, read the end of a failed CI job’s log (where GitHub has already masked the repository’s secrets), and ask for an action. Everything else (switching “Allow actions”, generating protocol secrets, adding or deleting anything, settings, approving) is refused.
  • Whether a request came from the screen or an assistant is decided by the key it carries, never by anything in the request, so the activity log can be trusted. An assistant’s own name is a label for you, not proof: the token decides what it may do.

An assistant’s action request is checked first (the action exists, its account allows actions, it isn’t marked dangerous, its rules allow it). Then it waits: a desktop notification and a dialog in every open window. Approve, and it runs; decline, or no answer within 2 minutes, and nothing runs, the assistant is told, and the attempt is recorded.

The keys file lives in your profile, not in any project (where), so an agent working in a repository never comes across it. The installed app keeps it encrypted, with a key your system’s store for secrets locks to you on this computer, so a copy of the file elsewhere (a backup, a synced folder) is no use.

  • Keeping keys from programs running as you. The encryption stops a copied file, not a program running as your user, which can ask the system to unlock the key just as Periskopos does (threat C either way).
  • Rate limits. Every action asks unless a rule or a grant you set says otherwise, and those are per action and revocable.
  • Exposing Periskopos beyond localhost (cloud agents). That changes the threat model entirely (real authentication, TLS, OAuth for MCP).

Please report it privately, as SECURITY.md explains. The full design record, with its history, is docs/AGENT-SAFETY.md in the repository.