← News
Security research

claude-mem runs an unpinned dependency with your full credentials

17 April 2026 · 6 min read

An adoption-risk analysis of thedotmack/claude-mem, the Claude Code memory plugin, focused on its Chroma-MCP subsystem.

Executive summary

claude-mem is a widely used Claude Code plugin that gives the agent persistent memory across sessions. We pointed Oplane at it and focused on the Chroma-MCP subsystem, the vector-search pipeline behind its semantic recall. The plugin’s own code is reasonable and, in places, clearly careful. The risk is not in what claude-mem ships. It is in what it assembles and runs on your machine at startup.

On first use, claude-mem launches its vector backend by shelling out to uvx and pulling chroma-mcp straight from PyPI:

uvx --python 3.13 chroma-mcp --client-type persistent --data-dir ~/.claude-mem/chroma/
  • No version pin. chroma-mcp is passed to uvx with no version constraint, so it resolves to whatever the latest release on PyPI happens to be that day.
  • No integrity check. There is no checksum, signature, or hash validation on the downloaded package before it executes.
  • Full environment inheritance. The subprocess receives the parent environment minus CLAUDECODE_*. In practice that still includes AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, NPM_TOKEN, SSH_AUTH_SOCK, and anything else living in your shell.

Why your scanner never sees it

Here is the part that makes this a blind spot rather than a bug. chroma-mcp is never written down. It does not appear in a package.json, a requirements.txt, or any lockfile. It is a bare string handed to uvx at runtime. Software composition analysis tools like Snyk, Dependabot, and Socket work by reading manifests and lockfiles, so this dependency is invisible to every one of them. You can run a clean audit of the repository and still have no idea this package executes on your laptop with your credentials.

The blast radius

On a normal day none of this fires. The subprocess runs as you, on your machine, and does its job. The problem is the shape of the exposure: an unpinned, unverified package, fetched fresh from a public registry, run with your full credential set, on every developer who installs the plugin. If that package is ever compromised (a typosquat, a maintainer-account takeover, a single bad release), it runs with everything your shell can reach. That is the textbook runtime supply chain path, and it is open by default here.

What Oplane flagged

  1. Pin and integrity-check the chroma-mcp subprocess before it runs

    Critical

  2. Scope the subprocess environment to an allowlist, not the full credential set

    High

  3. Add a retention and deletion path for the on-disk vector store

    Medium

  4. Stop passing the remote Chroma API key as a command-line argument

    Low

The fix is small

Two changes cover the critical path. Pin the version (chroma-mcp==X.Y.Z) so you decide what runs instead of PyPI deciding for you, and narrow the environment filter to an allowlist so the subprocess gets PATH and HOMErather than your cloud keys. Neither touches behavior. Both take the blast radius from “everything in your shell” down to almost nothing.


In fairness: we reported this, the maintainer disputed parts of it, and they are right that claude-mem’s own code is not malicious. On a single-user machine with full-disk encryption, the day-to-day risk is modest. The point was never that this one plugin is dangerous. It is that “popular, audited, healthy-looking” tells you nothing about what a tool assembles at runtime, and runtime is where the supply chain actually lives.

Stars, commit cadence, and a clean repository scan all looked fine here. The execution path was where the risk lived, and you only see it if you follow the data flow instead of the manifest.

Find the dependencies your scanner can't see

Oplane threat-models your architecture at the data-flow level and catches the runtime supply chain that manifest-based scanners miss.

We value your privacy

We use cookies to make the site work better for you and to analyze traffic. You can accept all cookies, customize your settings, or reject non-essential cookies.