mirror of
https://github.com/zadam/trilium.git
synced 2026-09-12 11:40:19 +05:00
The MCP endpoint was unauthenticated, relying on a loopback source-IP check plus the SDK's DNS-rebinding Host allow-list. That had three problems: - Loopback is not a credential. Any local process (a package postinstall script, another user on a shared box) could read and rewrite every note. - The Host allow-list was the only thing between a malicious page and the database, so a single parsing bug or a proxy that rewrites Host lost everything. - Because req.ip honours trust proxy, a misconfigured trustedReverseProxy could forge X-Forwarded-For: 127.0.0.1 and walk straight in. It also made the endpoint unusable in the deployment people actually have: under Docker, host traffic arrives from the bridge gateway rather than 127.0.0.1, so port mapping alone never satisfied the check (#10646). Require an ETAPI token on every request instead, mirroring what the web clipper already does on the server build. This makes the rebinding protection redundant rather than merely inconvenient — rebinding borrows the victim browser's network position, and a bearer token is not ambient authority, since cross-origin JS cannot set Authorization without a CORS preflight we never approve. The Host allow-list is therefore dropped; it would only have blocked legitimate remote clients, whose Host is their own domain. Only the Authorization header authenticates, never a session cookie, which would make /mcp CSRF-able with full tool access. The 401 deliberately omits WWW-Authenticate: in MCP that header triggers OAuth discovery (RFC 9728) and must point at protected-resource metadata, so advertising one would send spec-compliant clients into a flow Trilium cannot serve. Adds a rate limiter mirroring the login one (15 min / 10 / skip successful) since token guessing is otherwise unbounded once reachable off-loopback. BREAKING CHANGE: existing MCP clients must send an ETAPI token. MCP is off by default, so this affects only users who explicitly enabled it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
12 lines
197 B
JSON
12 lines
197 B
JSON
{
|
|
"mcpServers": {
|
|
"trilium": {
|
|
"type": "http",
|
|
"url": "http://localhost:8080/mcp",
|
|
"headers": {
|
|
"Authorization": "Bearer ${TRILIUM_ETAPI_TOKEN}"
|
|
}
|
|
}
|
|
}
|
|
}
|