[ ⌘K ]
← BACK TO SEARCH

jingwei950/clickup-mcp-server

critical

No description

This MCP server provides a remote interface to the ClickUp project management API, allowing AI agents to manage workspaces, spaces, folders, lists, ta...

purpose: This MCP server provides a remote interface to thethreat: network exposed
JavaScript0May 20, 2026May 20, 2026GITHUB
5/20/2026
high1 finding
src/tools/space.ts
68  server.tool(
69    "createSpace",
70    "Create a new space in the specified workspace with given features",
71    {
72      workspaceId: z.string(),
73      name: z.string(),
74      multipleAssignees: z.boolean(),
75      features: z.object({ ... }),
76    },
77    async ({ workspaceId, name, multipleAssignees, features }) => {
78      const apiKey = getApiKey();
79      if (!apiKey)
80        return { content: [{ type: "text", text: "API key missing." }] };
81      const payload = { ... };
82      const result = await callClickUpApi(
83        `team/${workspaceId}/space`,
84        "POST",
85        apiKey,
86        payload
87      );
88      return { content: [{ type: "text", text: JSON.stringify(result) }] };
89    }
90  );
src/tools/space.ts:68-113src/tools/folder.ts:109-126src/tools/list.ts:120-126src/tools/task.ts:260-271src/tools/document.ts:183-207

// Network-exposed MCP server; any client can invoke destructive tools.

The MCP server exposes tools that allow creating, updating, and deleting spaces, folders, lists, tasks, and documents. Any user with access to the MCP endpoint can perform destructive actions (delete spaces, tasks, etc.) without any additional authorization beyond the API key. The intended purpose is to manage ClickUp resources, but the scope is excessive because it includes deletion and modification without any safeguards or user confirmation.

ImpactAn attacker with access to the MCP endpoint (or a compromised LLM) can delete or modify critical project management data, causing data loss or disruption.

FixImplement role-based access control or require explicit confirmation for destructive operations. Consider separating read-only and write tools, or adding an approval step for deletions.

high1 finding
src/index.ts
69    const getApiKey = () => {
70      const store = context.getStore();
71      const headerKey = store?.request?.headers.get("X-ClickUp-API-Key") || "";
72      return headerKey || this.env.CLICKUP_API_KEY;
73    };
src/index.ts:69-73

// Network-exposed MCP server; API key can be intercepted if HTTPS is not enforced.

The API key is passed via an HTTP header (X-ClickUp-API-Key) or stored in an environment variable. The header-based transmission over HTTP (not HTTPS enforced) could expose the key in transit. Additionally, the key is used directly in the Authorization header without any encryption or masking.

ImpactAn attacker with network access could intercept the API key, gaining full access to the ClickUp account with the same permissions as the authorized user.

FixEnforce HTTPS for all communications. Consider using short-lived tokens or OAuth instead of long-lived API keys. Store the key securely and avoid passing it in headers from untrusted clients.

medium1 finding
src/index.ts
19async function invokeClickUpApi(
20  path: string,
21  method: string,
22  apiKey: string,
23  body?: any
24) {
25  let apiVersion = "v2";
26  let endpointPath = path;
27  if (path.startsWith("/v3")) {
28    apiVersion = "v3";
29    endpointPath = path.slice(3);
30  }
31  const baseUrl = `https://api.clickup.com/api/${apiVersion}`;
32  const url = `${baseUrl}${
33    endpointPath.startsWith("/") ? endpointPath : `/${endpointPath}`
34  }`;
src/index.ts:19-36

// Network-exposed MCP server; limited to ClickUp API domain but could access unintended endpoints.

The invokeClickUpApi function constructs a URL by concatenating a base URL with a user-supplied path. Although the base URL is fixed to ClickUp's API, the path is derived from tool parameters (e.g., spaceId, folderId). If an attacker can control the path parameter (e.g., by passing a string like '../../other-api'), they could potentially make requests to unintended endpoints within the ClickUp API or even external URLs if the base URL were not fixed. However, the base URL is hardcoded, so the risk is limited to path traversal within the ClickUp API domain.

ImpactAn attacker could potentially access other ClickUp API endpoints not intended by the tool, such as admin or billing endpoints, depending on the API key's permissions.

FixValidate that the path starts with an expected prefix and does not contain '..' or other traversal sequences. Use a whitelist of allowed paths.

medium1 finding
src/tools/space.ts
119  server.tool(
120    "getSpace",
121    "Fetch metadata for a specific space",
122    { spaceId: z.string() },
123    async ({ spaceId }) => {
124      const apiKey = getApiKey();
125      if (!apiKey)
126        return { content: [{ type: "text", text: "API key missing." }] };
127      const result = await callClickUpApi(`space/${spaceId}`, "GET", apiKey);
128      return { content: [{ type: "text", text: JSON.stringify(result) }] };
129    }
130  );
src/tools/space.ts:119-126src/tools/folder.ts:131-139src/tools/list.ts:66-72src/tools/task.ts:210-216src/tools/document.ts:213-223

// Network-exposed MCP server; limited impact as ClickUp API likely validates IDs.

Tools accept resource IDs (spaceId, folderId, listId, taskId, etc.) as strings but do not validate that they conform to expected formats (e.g., numeric IDs). While the ClickUp API may reject invalid IDs, the lack of validation could allow injection of unexpected characters into the URL path, potentially leading to SSRF or API abuse if the ClickUp API has any path-based vulnerabilities.

ImpactAn attacker could craft IDs that cause the server to make requests to unintended ClickUp API endpoints or include special characters that exploit API quirks.

FixValidate that IDs match expected patterns (e.g., numeric strings) and sanitize inputs before constructing URLs.

shell.execnetwork.httpenv.exposureauth.none
80
LLM-based
high findings+50
medium findings+30