GitHub Security Advisory: GHSA-g9rg-8vq5-mpwm
Package: mcp-memory-service (PIP)
Severity: HIGH (CVSS 8.1)
CWE: CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains
Vulnerable versions: < 10.25.1
Patched in: 10.25.1

Summary: mcp-memory-service's Wildcard CORS with Credentials Enables Cross-Origin Memory Theft

Details:
### Summary
When the HTTP server is enabled (`MCP_HTTP_ENABLED=true`), the application configures FastAPI's CORSMiddleware with `allow_origins=['*']`, `allow_credentials=True`, `allow_methods=["*"]`, and `allow_headers=["*"]`. The wildcard `Access-Control-Allow-Origin: *` header permits any website to read API responses cross-origin. When combined with anonymous access (`MCP_ALLOW_ANONYMOUS_ACCESS=true`) - the simplest way to get the HTTP dashboard working without OAuth - no credentials are needed, so any malicious website can silently read, modify, and delete all stored memories.


### Details
### Vulnerable Code

**`config.py:546` - Wildcard CORS origin default**

```python
CORS_ORIGINS = os.getenv('MCP_CORS_ORIGINS', '*').split(',')
```

This produces `['*']` by default, allowing any origin.

**`app.py:274-280` - CORSMiddleware configuration**

```python
# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=CORS_ORIGINS,        # ['*'] by default
    allow_credentials=True,             # Unnecessary for anonymous access; bad practice
    allow_methods=["*"],
    allow_headers=["*"],
)
```

### How the Attack Works

The wildcard CORS default means every API response includes `Access-Control-Allow-Origin: *`. This tells browsers to allow **any website** to read the response. When combined with anonymous access (no authentication required), the attack is straightforward:

```javascript
// Running on https://evil.com - reads victim's memories
// No credentials needed - anonymous access means the API is open
const response = await fetch('http://192.168.1.100:8000/api/memories');
const memories = await response.json();
// memories contains every stored memory - passwords, API keys, personal notes
```

The browser sends the request, the server responds with `ACAO: *`, and the browser allows the JavaScript to read the response body. No cookies, no auth headers, no credentials of any kind.

**Clarification on `allow_credentials=True`:** The advisory originally stated that Starlette reflects the `Origin` header when `allow_credentials=True` with wildcard origins. Testing with Starlette 0.52.1 shows that **actual responses return `ACAO: *`** (not the reflected origin); only preflight `OPTIONS` responses reflect the origin. Per the Fetch specification, browsers block `ACAO: *` when `credentials: 'include'` is used. However, this is irrelevant to the attack because **anonymous access means no credentials are needed** - a plain `fetch()` without `credentials: 'include'` works, and `ACAO: *` allows it.

### Two Attack Vectors

This misconfiguration enables two distinct attack paths:

**1. Cross-origin browser attack (CORS - this advisory)**
- Attacker lures victim to a malicious webpage
- JavaScript on the page reads/writes the memory service API
- Works from anywhere on the internet if the victim visits the page
- The `ACAO: *` header is what allows the browser to expose the response to the attacker's JavaScript

**2. Direct network ac