[ ⌘K ]
← BACK TO SEARCH

kintopp/rijksmuseum-mcp-plus

critical

MCP server for the Rijksmuseum collections with extended metadata, semantic search, provenance analysis, similarity comparisons and spatial reasoning.

MCP server (purpose undetermined)

purpose: MCP server (purpose undetermined)threat: network exposed
Python13May 19, 2026May 20, 2026GITHUB
articonclasslinked-datamcp-serverprovenancesemantic-search
5/20/2026
high2 findings
src/index.ts
48    return execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
medium1 finding
src/index.ts
273  const allowedOrigins = process.env.ALLOWED_ORIGINS;
274  app.use(
275    cors({
276      origin: allowedOrigins ? allowedOrigins.split(",") : "*",
277    })
278  );
src/index.ts:7

// Network-exposed MCP, exploitable by any website when ALLOWED_ORIGINS is not configured.

When ALLOWED_ORIGINS is not set, the CORS middleware allows all origins (*). This means any website can make cross-origin requests to the MCP server, potentially enabling CSRF-like attacks if the server is exposed to the network.

ImpactAn attacker could trick a user's browser into making requests to the MCP server, potentially executing tools on behalf of the user if the server relies on browser-based authentication (though this server has no auth).

FixSet a restrictive default or require explicit configuration. Use an allowlist of known origins instead of wildcard.

medium1 finding
src/index.ts
367  app.get("/similar/:uuid", (req: express.Request, res: express.Response) => {
368    const page = similarPages.get(req.params.uuid as string);
369    if (!page) {
370      res.status(404).json({ error: "Page not found or expired (30 min TTL)" });
371      return;
372    }
373    page.lastAccess = Date.now();
374    res.type("html").send(page.html);
375  });
376
377  app.get("/enrichment-review/:uuid", (req: express.Request, res: express.Response) => {
378    const page = enrichmentReviewPages.get(req.params.uuid as string);
379    if (!page) {
380      res.status(404).json({ error: "Page not found or expired (30 min TTL)" });
381      return;
382    }
383    page.lastAccess = Date.now();
384    res.type("html").send(page.html);
385  });
src/index.ts:367

// Exploitable only if MCP is exposed to untrusted prompts and the attacker can make HTTP requests to the server.

The /similar/:uuid and /enrichment-review/:uuid endpoints accept a UUID parameter from the URL path and use it directly as a key to retrieve a page from an in-memory Map. There is no validation that the parameter is a valid UUID format. While this does not lead to injection (the key is used only for Map lookup), it could allow an attacker to enumerate valid UUIDs by observing response times or error messages. Additionally, if the Map were to contain sensitive data, an attacker could access it by guessing UUIDs.

ImpactAn attacker could potentially enumerate valid session/page UUIDs, leading to information disclosure of stored HTML pages. The pages are intended to be shared via UUID, so the impact is limited to unauthorized access if the UUID is guessed.

FixValidate that the :uuid parameter matches a UUID format (e.g., using a regex or uuid library) before using it as a Map key. Also consider rate-limiting to prevent brute-force enumeration.

medium1 finding
src/index.ts
118  const url = process.env[spec.urlEnvVar];
119  if (!url) return;
120  console.error(`Downloading ${spec.name} DB...`);
121  const dir = path.dirname(dbPath);
122  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
123  const tmpPath = dbPath + ".tmp";
124  const controller = new AbortController();
125  const downloadTimer = setTimeout(() => controller.abort(), 330_000);
126  try {
127    const res = await fetch(url, { redirect: "follow", signal: controller.signal });
src/index.ts:11

// Local-only MCP, requires compromised LLM or environment variable control to exploit.

The ensureDb function fetches a URL from an environment variable (e.g., VOCAB_DB_URL) without validating the scheme or host. An attacker who can set environment variables (e.g., via a compromised CI/CD pipeline or local access) could point the URL to an arbitrary endpoint, leading to server-side request forgery (SSRF) or downloading malicious content.

ImpactAn attacker could cause the server to fetch arbitrary URLs, potentially exfiltrating data or downloading malicious files that could be loaded as databases.

FixValidate that the URL uses an allowed scheme (e.g., https://) and restrict to known hosts. Consider using a fixed base URL or verifying the URL against an allowlist.

low1 finding
src/index.ts
421  app.get("/debug/memory", (_req: express.Request, res: express.Response) => {
422    res.json(captureMemorySnapshot(buildMemoryDbHandles()));
423  });
src/index.ts:421

// Exploitable only if MCP is exposed to untrusted prompts and the attacker can make HTTP requests to the server.

The /debug/memory endpoint is unauthenticated and exposes detailed memory statistics, including database file paths and internal state. While the comment states it is 'operational signal, not sensitive', it could leak information about the server's internal structure, such as file paths and database sizes, which could aid an attacker in crafting more targeted attacks.

ImpactAn attacker could gain insight into the server's configuration, including file paths and memory usage patterns, potentially aiding in path traversal or denial-of-service attacks.

FixAdd authentication or restrict access to internal networks. Alternatively, remove the endpoint or limit the information returned.

low1 finding
src/index.ts
367  app.get("/similar/:uuid", (req: express.Request, res: express.Response) => {
368    const page = similarPages.get(req.params.uuid as string);
369    if (!page) {
370      res.status(404).json({ error: "Page not found or expired (30 min TTL)" });
371      return;
372    }
373    page.lastAccess = Date.now();
374    res.type("html").send(page.html);
375  });
src/index.ts:27

// Network-exposed MCP, but impact is limited to reading cached HTML pages.

The /similar/:uuid route accepts a UUID parameter and uses it directly as a key to retrieve a page from a Map. While this is not a path traversal or injection, it could allow an attacker to enumerate valid UUIDs if the Map contents are predictable. However, the impact is limited to retrieving cached HTML pages.

ImpactAn attacker could potentially access cached HTML pages if they can guess or enumerate UUIDs, but the pages are intended to be publicly accessible.

FixConsider adding rate limiting or authentication if the pages contain sensitive information. Otherwise, this is low risk.

network.httpbrowser.automationenv.exposureshell.execfilesystem.readfilesystem.writeauth.none
100
LLM-based
low findings+10
high findings+50
medium findings+45