Please report security issues via GitHub private advisory or email [email protected]. Do NOT open public issues for vulnerabilities.
| Version | Supported |
|---|---|
| 0.1.x | Yes |
- XSS prevention: All markdown rendering uses DOMPurify sanitization
- Content Security Policy: Strict CSP header limits script/style sources to self + cdnjs
- Frame protection:
X-Frame-Options: DENYprevents clickjacking - CORS: Restricted to localhost origins only
- Path traversal protection: All file access endpoints validate against indexed sources; symlinked files are rejected
- Error masking: Filesystem paths are stripped from error responses
mm web ships an unauthenticated SPA on the loopback interface. CORS is a
browser readability boundary, not a write boundary — a malicious tab can
issue CORS-simple POST requests against http://127.0.0.1:<port> and the
handler still runs even if the response is unreadable. To close that gap,
every unsafe-method request to /api/** (POST / PUT / PATCH / DELETE) is
gated by a single middleware that checks three things at once:
- CSRF token —
X-Memtomem-CSRFmust match the per-process token inapp.state.csrf_token. The SPA fetches it viaGET /api/sessionlazily on the first unsafe-method request (cached for the page lifetime); the token rotates on every restart and is never persisted. - Origin / Referer — when present, must resolve to a loopback host
or an operator-supplied
--trusted-originentry. Defends drive-by tabs whose Origin reveals the attacker domain. - Host header — must be a loopback hostname or an operator-supplied
--trusted-hostentry. Defends DNS rebinding, where the socket peer is127.0.0.1but the browser's URL bar (and theHost:header) is attacker-controlled.
Failures return 403 with a JSON {"detail": "..."} body and a
structured web.csrf.observe log record for after-the-fact auditing.
Operator surface:
--allow-remote-ui— required when--hostis non-loopback. Startup refuses without it; the unauthenticated SPA must not be exposed to the network by accident.--trusted-origin <host>(repeatable) — extends the Origin/Referer allow-list. Pair with--allow-remote-ui.--trusted-host <host>(repeatable) — extends the Host-header allow-list. Pair with--allow-remote-ui.MEMTOMEM_WEB__CSRF_ENFORCE— emergency rollback to observe-only. Set to0/false/no/offto keep the structured log line but skip the 403. Any other value (including unset and typos) keeps enforcement on.
- SSRF protection: Private/reserved IP ranges blocked (10.x, 172.16-31.x, 192.168.x, 169.254.x, localhost, ::1)
- Protocol restriction: Only
http://andhttps://allowed - Redirect validation: Each redirect hop is validated against the same IP blocklist
- Internal hostname blocking:
.local,.internalTLD hosts are rejected
- SQL injection: All queries use parameterized statements
- No unsafe deserialization: No pickle, no unsafe YAML loading
- No command injection: No subprocess/eval/exec with user input
- Path validation: CLI uses
Path.relative_to()for directory containment checks
- Never commit API keys or credentials
- Use MCP client
envblocks for configuration - Default storage is local SQLite — no network exposure
- Web UI binds to
127.0.0.1by default — not publicly accessible - Set
MEMTOMEM_TOOL_MODE=standardto reduce tool surface area for AI agents