Security¶
Reporting a vulnerability¶
Please use GitHub's private vulnerability reporting ("Report a vulnerability" on the repository's Security tab). If that is not available to you, open a regular issue that describes the problem in general terms, and leave out exploit details, secrets, DSNs, transcripts and memory contents. This is a personal project, so I can't promise a response time, but security reports come first.
Threat model in brief¶
claude-memory runs as your user on your machine. It stores what it learns in a Postgres database that you operate.
- No network listener. The MCP server speaks stdio only. Claude Code starts
it as a child process. Outbound, it talks to your Postgres, your Ollama
(local by default) and the
claude,git,az,ghandglabCLIs. - Database credentials come only from the environment or from
~/.config/claude-memory/env. The binary refuses that file if it is group- or world-readable (it must be 0600), and it never shell-sources it.doctorandinstallmask the password in their output. The server recipe inDEPLOY.mdbinds Postgres to loopback and a Tailscale address, usesscram-sha-256authentication, and letspg_hba.confreject everything outside the tailnet range. - Secret scrubbing is best-effort. Session transcripts and PR text are
redacted before they are sent to Anthropic through your own
claude -p --model haiku. Every record is scrubbed again before it is written to Postgres. The scrubber matches known patterns: bearer tokens, private-key blocks, URLs with passwords, AWS access keys, GitHub tokens, JWTs, Azure DevOps PATs, andsecret/key/token/password = "..."assignments. It is not a guarantee. A secret in an unrecognised format can get through, so don't paste credentials into sessions you expect to be remembered. Embeddings are computed by your Ollama and never leave the machine unless you pointMEMORY_OLLAMA_URLelsewhere. - Untrusted PR authors are filtered. On GitHub, only PRs and comments by
OWNER,MEMBERorCOLLABORATORare ingested. On GitLab, only those by Developer-or-higher project members are ingested. Bots are skipped on both. Everything else is dropped before extraction. Azure DevOps content is treated as trusted because access is limited to the organisation's members. Thegh/glab/azCLIs run with their own login. Token variables such asGH_TOKENare removed from their environment. - Retrieved memory is a prompt-injection surface. The hook and
memory_searchput stored text into Claude's context. Hook cards carry only title, repo and id, under a header that marks them as unverified hints to confirm withmemory_get. Candidates are flagged as unverified. These are labels, not a sandbox. Anyone who can write to your database, and any text that reached a record through a session or a trusted PR, can influence Claude's behaviour in later sessions. Treat write access to the database as equivalent to write access to your prompts, review candidates (claude-memory review; note that PR-derived records are stored asactiveand skip this step), and runimportandingest-prwith--dry-runfirst. - Namespaces are for relevance, not isolation. All namespaces share one database and one role. Use separate databases if you need a hard boundary.