MCP Documentation Server Exposed Its Knowledge Base Without Authentication — CVE-2026-54504
A newly published advisory describes an unsafe network default in @andrea9293/mcp-documentation-server 1.13.0. Its automatically started Web UI and document-management API listened on all interfaces at port 3080, while the API required no authentication. A client on a reachable LAN, VPN, VM network, or container bridge could enumerate, read, search, add, and delete documents in the server's knowledge base.
The issue is tracked as CVE-2026-54504 and GHSA-6f5r-5672-72j7. GitHub rates it High, CVSS 3.1 8.8 (AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). The affected range is unusually narrow: the advisory lists version 1.13.0 specifically, with 1.13.1 as the first patched release. Later releases inherit the fix.
“localhost” in the instructions was not a bind policy
The project's documentation told users to open http://localhost:3080, but the implementation called the Express listener with only a port. On Node.js, omitting the host makes the service listen on the unspecified address—observed as *:3080—rather than restricting it to 127.0.0.1. A local-looking URL in setup instructions therefore concealed a network-reachable service.
The Web UI starts unless START_WEB_UI=false. According to the advisory's reproduction, unauthenticated requests through the host's LAN address succeeded against configuration, document-listing, document-read, document-add, corpus-search, and document-delete endpoints. This is not described as remote code execution; the direct impact is unauthorized administration of the retrieval corpus.
That distinction still carries agent-specific risk. Documents are not passive files when an MCP assistant retrieves and trusts them as working context. An intruder who can insert or modify corpus material gains a durable route to misinformation or prompt injection, while read access can expose proprietary documentation and delete access can remove both operational knowledge and evidence of tampering.
The patch changes the default exposure boundary
Version 1.13.1 binds the Web UI to 127.0.0.1 by default and adds a WEB_HOST setting for deliberate changes. The relevant commit and release landed on June 4; GitHub published the advisory on July 15. Teams that track CVE publication rather than package releases should verify their deployed version rather than assuming a recent installation is current.
The fix addresses the reported default-network exposure by making the service local-only. It should not be read as authentication for intentional remote operation. If an operator sets WEB_HOST=0.0.0.0 or publishes the port through a container, the document API still needs an authenticating reverse proxy, authorization policy, TLS, and network restrictions appropriate to the corpus.
The advisory maps the flaw to missing authentication and exposure of a resource to the wrong sphere. That pairing is useful: either control would have reduced impact, but secure local tooling should apply both. Bind narrowly so an accidental missing-auth route is not network reachable, and authenticate so a later bind or proxy change does not silently publish administrative functions.
Knowledge-base writes are agent control-plane writes
Traditional document systems often classify an unauthorized insert as data-integrity loss. In a retrieval-enabled agent, the same insert can alter future tool selection, conclusions, generated code, or actions. The poisoned content persists after the original network session and may be surfaced only for particular searches, making the compromise difficult to connect to its cause.
This is the storage-side counterpart to the tenant-isolation problem covered in the site's n8n-MCP backup advisory. Agent gateways create secondary state—documents, embeddings, snapshots, traces, and memory—that needs the same identity, authorization, tenant, retention, and audit controls as the upstream system. Protecting only MCP tool invocation leaves the management plane exposed.
Defensive engineering guidance
- Upgrade past 1.13.0. Install 1.13.1 or a later release, verify the resolved npm package version and lockfile, and restart every running server process or container.
- Confirm the actual listener. Inspect the host and container namespace for port 3080. The expected patched default is loopback-only; do not infer bind scope from the URL printed in documentation or logs.
- Disable the UI when it is unnecessary. Set
START_WEB_UI=falsefor stdio-only or headless MCP deployments that do not require document administration. - Investigate affected deployments. For systems that ran 1.13.0 on a shared network, review reverse-proxy, firewall, container, VPN, and host logs for access to
/api/documents,/api/search-all, and related endpoints. Reconcile the current corpus against trusted source material and backups. - Rebuild embeddings after cleanup. Removing an inserted source document may not be sufficient if chunks, indexes, caches, or generated summaries survive elsewhere. Regenerate derived retrieval state from a known-good corpus.
- Put remote administration behind identity. If network access is intentional, require TLS, authentication, per-operation authorization, request logging, rate limits, and explicit ingress allowlists. Do not expose port 3080 directly.
- Separate read and administration paths. The agent's retrieval identity should not automatically gain document add or delete permissions. Treat corpus mutation as a privileged, reviewable control-plane action.
- Test from outside the process namespace. CI should start the service with default settings and verify that another container or network namespace cannot connect, while localhost can. Add unauthenticated negative tests for every management endpoint.
CVE-2026-54504 shows why a development convenience can become an agent control-plane vulnerability. A UI can look local in a README and still listen everywhere; a document API can look like ordinary CRUD and still determine what an assistant believes. Secure defaults must be enforced by the socket, the identity layer, and the corpus authorization model—not by the URL an operator was told to type.
Sources: