Skip to content

Harden HTTP/SSE transport: basic-memory mcp defaults to 0.0.0.0 with no auth (contradicts SECURITY.md) #1578

Description

@tonydzi

Hardening: basic-memory mcp HTTP/SSE transport defaults to 0.0.0.0 with no auth — contradicts SECURITY.md

Class: unsafe default. No exploit/PoC attached — reporting publicly per your SECURITY.md's own guidance, since this is a config-default hardening issue with no novel exploitation primitive.

What

basic-memory mcp --transport streamable-http (and sse) defaults --host to 0.0.0.0:

src/basic_memory/cli/commands/mcp.py (@ 3bf2d523):

host: str = typer.Option(
    "0.0.0.0", help="Host for HTTP transports (use 0.0.0.0 to allow external connections)"
),

The HTTP transport is served with no authentication and no Origin/Host allow-list. The only middleware registered on the server is MCPClientInfoMiddleware (src/basic_memory/mcp/server.py:272); CLIAuth there is for loading the outbound cloud OAuth token, not for gating inbound requests. So a single basic-memory mcp --transport streamable-http binds every knowledge-base tool — write_note, read_note, read_content, delete_note, create_memory_project, etc. — to all interfaces, unauthenticated, reachable by anyone on the LAN.

Why this is worth fixing

It directly contradicts the project's own SECURITY.md:

  • Basic Memory does not open network ports by default. The MCP server uses stdio; the optional REST API is intended for localhost use.
  • If exposing the REST API, bind it only to localhost.

The default is to open a port on all interfaces the moment a user picks an HTTP transport, and there is no localhost binding by default. A user following the docs to run the recommended web transport gets the opposite of what SECURITY.md promises. create_memory_project also lets a caller point a project at an arbitrary local path (by design for a personal tool), which raises the impact of the port being reachable off-host.

Related: with no Host/Origin check, a 0.0.0.0 (or even 127.0.0.1) listener is exposed to DNS-rebinding from a browser tab. I have not verified whether the underlying fastmcp 4.x / mcp stack adds any origin protection of its own, so I'm flagging this as a consideration rather than a confirmed gap — worth a look while touching this code.

Suggested fix (minimal)

  1. Default --host to 127.0.0.1; keep 0.0.0.0 as an explicit opt-in.
  2. When the user does pass a non-loopback host, log a one-line startup warning that the transport is unauthenticated and reachable off-host.
  3. (Optional, stronger) add an allowed-hosts / origin check for the HTTP transports to close the rebinding surface.

Happy to open a PR for (1)+(2) — it's a one-line default change plus a warning. Just confirm you'd take it and whether you'd rather keep 0.0.0.0 documented for the container path.

Prior art checked

No matching open/closed issues, 0 security advisories, private vuln reporting enabled. Filing publicly because this is hardening with no exploit; if you'd prefer this privately for any reason, say the word and I'll move it to a security advisory.


— TonyDzi (Palo Alto AI Research Lab) · this is a tiny piece of a bigger machine — a second brain + multi-agent fleet with persistent memory: github.com/tonydzi · DMs open. (Report drafted with an AI co-founder under my review.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions