Seshat AIDocumentation

Documentation / Concepts

Security and trust

What Seshat refuses to do by default: untrusted project files, secrets in commands, the local network and the gRPC server.

An agent reads files and runs commands, so what it reads can be hostile: a repository you just cloned, a web page, a tool result. Seshat is built so that the safe behaviour is the default and loosening it is a decision you take.

Project files are not trusted until you say so

A project folderseshat.json, .seshat.json,.seshat/seshat.json,SESHAT.md, AGENTS.md...Same hash as trusted ?for each filetrusted_projects.jsonin the runtime folder:the SHA-256 of each fileEverything appliesall sections of the configand the instruction filesThe risky parts are ignoredmcp, lsp, hooks, permissions,providers, multimedia providers,options.context_paths andoptions.skills_paths, and theinstruction filesStill appliedmodels, display options,disabled toolsseshat trustyou read the files, thenrecord their hashA file changesa pull, an edit: the hashdiffers, trust is withdrawncompareyesnorecords the hashask againYour own global file is never restricted.seshat trust --status lists the files;seshat trust --untrust withdraws the trust.
Trust is recorded for the exact content of each file. If a pull changes the file, the question comes back.

The terminal interface reads its configuration from your own files, and also from the project: .seshat.json or seshat.json (from the working directory up to the git root) and .seshat/seshat.json. A cloned repository can carry any of them.

Some sections run something or send something somewhere, so they are ignored until the project is trusted:

SectionWhy it is held back
mcp / mcpServersA stdio MCP server is a command line started when Seshat opens
hooksShell commands run on tool events
lspLanguage servers are programs
providersA base URL decides who receives your API key
permissionsallowed_tools removes the permission questions
image_generation, text_to_speech, speech_to_textEndpoints and keys
options.context_paths, options.skills_pathsThey can send any file of the machine to the model provider, or add instructions
SESHAT.md, AGENTS.md, .seshat/instructions.mdTheir text is added to the model’s instructions every turn

Models, display options and disabled tools still apply. Your own configuration, in the runtime folder, is never restricted. When something is ignored, the interface shows a warning at startup.

seshat trust              # trust this project's configuration files as they are now
seshat trust --status     # list the files, their state and what they hold
seshat trust --untrust    # withdraw the trust

Trust is recorded for the content of each file (its SHA-256). If a pull changes a file, it has to be trusted again.

The .env file of the working directory

Seshat also reads a .env in the folder where it starts. An entry is ignored, with a warning, when:

  • its value contains a shell substitution ($(...) or a backquote);
  • its name decides what runs or where Seshat looks for its configuration: PATH, SHELL, HOME, LD_*, GIT_*, NODE_OPTIONS, SESHAT_RUNTIME_ROOT, SESHAT_BASH_* and a few others.

Keys, models and URLs are still read. If a *_BASE_URL points outside your machine, Seshat applies it but prints a warning that names the server which will receive your requests and their API key.

Secrets stay out of the commands the model runs

The bash tool, background commands and the terminal’s shell no longer inherit the whole environment. Variables whose name says secret (*_API_KEY, *_TOKEN, *_SECRET, *_PASSWORD, DATABASE_URL…), the families used by the providers, and values that plainly look like credentials are removed. PATH, HOME, the locale, proxies and build settings stay.

SettingEffect
SESHAT_BASH_ENV_ALLOW=NAME,PREFIX_*Keep the variables you name, for a command that really needs GITHUB_TOKEN
SESHAT_BASH_INHERIT_ENV=trueGo back to passing the whole environment

The local network is off limits to web_fetch

The web fetch tool refuses loopback, private, link-local, carrier-grade NAT and multicast addresses, IPv4 addresses hidden in NAT64 addresses, and cloud metadata names, both before and after DNS resolution. A page cannot tell the agent to read your router or a cloud metadata endpoint.

The gRPC server is closed by default

cmd/grpc listens on 127.0.0.1. To listen elsewhere you must give it a token, or explicitly accept the risk:

SettingMeaning
SESHAT_GRPC_HOSTAddress to listen on. Anything other than loopback needs a token, or the server refuses to start
SESHAT_GRPC_AUTH_TOKENWith it, every call except HealthCheck needs authorization: Bearer <token>
SESHAT_GRPC_TLS_CERT, SESHAT_GRPC_TLS_KEYTurn TLS on
SESHAT_GRPC_ALLOW_STDIO_MCP=trueAllow ConnectMCP to start a stdio server. Refused by default
SESHAT_GRPC_ALLOW_INSECURE_REMOTE=trueListen on a non-local address with no token. Not recommended

Permissions

On top of all this, every sensitive action goes through the permission system. For each tool call, Seshat asks a fixed series of questions, in order. The first one that matches decides.

A tool call needs approvalDeny rule for this tool ?DeniedAsk rule for this tool ?AskThe tool refuses or asks ?Denied or askthe tool checks its own input: paths, commandsBypass mode ?Allowedonly rules can still objectA deny rule matches ?DeniedAn allow rule matches ?AllowedAn ask rule matches ?AskA read-only tool ?Allowedin every mode except neverAuto mode ?The classifier decidesno classifier: ask, or deny when headlessonRequest and a workflow tool ?Allowedagents, tasks, plan modeAsknothing matchedThen the answer is appliednever mode, or no way to ask (background run):an ask becomes a denial, and the model sees a failureotherwise the user is asked, and decidesyesyesyesyesyesyesyesyesyesyesnonononononononononoRULES AND THE TOOL ITSELFTHE PERMISSION ENGINE
Read from the top. The first question that matches decides. A deny rule always wins over an allow rule.

What to remember from it:

  • Deny always wins. A deny rule beats any allow rule, in every mode.
  • Bypass is not “no checks”. In bypass mode the questions disappear, but deny and ask rules still apply, and the safety check of the tool pipeline (see Inside the runtime) still runs.
  • Read-only tools never interrupt you. Search, reading and similar tools are allowed in every mode except never.
  • Auto mode without a classifier is not permissive. The classifier decides for each call when one is configured. With none configured, Seshat asks you in an interactive session and refuses in a headless one, so auto mode never turns into blanket approval.
  • Background runs cannot ask. In never mode, or whenever no one can answer, an “ask” becomes a denial and the model sees a failure it can work around.

The modes themselves are described in Using the CLI.

Updated on 2026-10-14