BACK TO SEARCH
Geektasticdad/mcp-servercritical

No description

This MCP server connects Claude to Microsoft 365 (email, calendar, OneDrive), GitHub (repos, issues, PRs), a Podcast Management App, and local Claude ...

purpose: This MCP server connects Claude to Microsoft 365 (threat: network exposed
TypeScript · 0 · Jun 9, 2026 · Jun 10, 2026 · GITHUB ↗
RISK SCORE
0/ 100 risk
high findings+75
medium findings+45
capped at100
VULNERABILITY ANALYSIS · 6 findings in 6 blocks3 HIGH · 3 MEDIUM
HIGH1 finding
src/connectors/podcast/tools.ts:46
46const data = await podcastFetch<Record<string, unknown>>(`/episodes/${id}`);
src/connectors/podcast/tools.ts:46

// Exploitable if the podcast API server has other endpoints that could be accessed via path traversal. Since the MCP is network-exposed, an attacker can directly call this tool.

EXPLAINThe podcast_get_episode tool accepts an 'id' parameter that is directly interpolated into the URL path without any validation. An attacker could provide a value like '../admin' or '../../etc/passwd' to traverse the API path and access unintended endpoints.
IMPACTAn attacker could access arbitrary endpoints on the podcast API server, potentially reading sensitive data or performing unauthorized actions beyond the intended episode retrieval.
FIXValidate that the 'id' parameter contains only alphanumeric characters, hyphens, or underscores. Reject any input containing '..', '/', or other path traversal sequences.
HIGH1 finding
src/connectors/podcast/tools.ts:104
104const data = await podcastFetch<{ id: string; title: string }>(`/episodes/${id}`, {
105  method: "PATCH",
106  body: JSON.stringify(updates),
107});
src/connectors/podcast/tools.ts:104

// Exploitable if the podcast API server has other endpoints that could be updated via path traversal. Since the MCP is network-exposed, an attacker can directly call this tool.

EXPLAINThe podcast_update_episode_confirmed tool accepts an 'id' parameter that is directly interpolated into the URL path without validation. An attacker could provide a path traversal payload to update resources on unintended endpoints.
IMPACTAn attacker could update arbitrary resources on the podcast API server, potentially modifying sensitive data or performing unauthorized actions.
FIXValidate that the 'id' parameter contains only alphanumeric characters, hyphens, or underscores. Reject any input containing '..', '/', or other path traversal sequences.
HIGH1 finding
src/connectors/podcast/tools.ts:4
4function podcastApiUrl(path: string): string {
5  const base = process.env.PODCAST_API_URL?.replace(/\/$/, "") ?? "";
6  return `${base}${path}`;
7}
src/connectors/podcast/tools.ts:4

// Exploitable if an attacker can control the PODCAST_API_URL environment variable or inject path traversal characters into the path parameter. Since the MCP is network-exposed, an attacker could potentially influence the path via tool inputs.

EXPLAINThe podcastApiUrl function constructs the API URL by concatenating an environment variable (PODCAST_API_URL) with a user-controlled path. If an attacker can control the environment variable or the path (e.g., via path traversal), they could redirect requests to arbitrary internal or external hosts, enabling SSRF attacks.
IMPACTAn attacker could make the server send requests to internal services (e.g., cloud metadata endpoints, internal APIs) or external malicious servers, potentially leaking sensitive data or performing unauthorized actions.
FIXValidate that PODCAST_API_URL is a well-formed URL with an allowed hostname. Additionally, validate the path parameter to prevent path traversal (e.g., reject paths containing '..' or starting with '/').
MEDIUM1 finding
src/connectors/m365/tools.ts:56
56}, async ({ to, subject, body }) => {
57  const token = await getM365Token(["Mail.Send"]);
58  await graph("/me/sendMail", token, {
59    method: "POST",
60    body: JSON.stringify({
61      message: {
62        subject,
63        body: { contentType: "Text", content: body },
64        toRecipients: [{ emailAddress: { address: to } }],
65      },
66    }),
67  });
src/connectors/m365/tools.ts:56

// Exploitable if an attacker can call the confirmed tool directly, bypassing the initial validation. Since the MCP is network-exposed, an attacker can call any tool.

EXPLAINThe m365_send_email_confirmed tool accepts a 'to' parameter that is validated as an email in the initial tool (m365_send_email) but not in the confirmed version. The confirmed tool uses a simple string schema without email validation, allowing an attacker to send emails to arbitrary addresses or potentially inject multiple recipients via crafted input.
IMPACTAn attacker could send emails to unintended recipients, potentially bypassing the initial validation and causing spam or phishing attacks from the user's account.
FIXAdd email validation to the 'to' parameter in m365_send_email_confirmed, e.g., z.string().email(). Additionally, consider validating that the address is a single email and not a list.
MEDIUM1 finding
src/connectors/github/tools.ts:30
30const [owner, repoName] = repo.split("/");
31const octokit = getOctokit();
32const { data } = await octokit.issues.listForRepo({ owner, repo: repoName, state, per_page: limit });
src/connectors/github/tools.ts:30

// Exploitable if the GitHub API has endpoints that interpret path traversal sequences. Since the MCP is network-exposed, an attacker can directly call this tool.

EXPLAINThe github_list_issues tool accepts a 'repo' parameter in 'owner/repo' format. While the split('/') limits to two parts, an attacker could provide a repo name containing path traversal sequences like '..' which might be passed to the GitHub API. Although the GitHub API may reject such values, this could still lead to unexpected behavior or information disclosure if the API interprets them differently.
IMPACTAn attacker might be able to list issues from unintended repositories or cause the tool to behave unexpectedly, potentially leaking information about repository existence or structure.
FIXValidate that the 'repo' parameter matches a strict pattern like /^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$/. Additionally, validate that the split results in exactly two non-empty parts.
MEDIUM1 finding
src/connectors/github/tools.ts:63
63const [owner, repoName] = repo.split("/");
64const octokit = getOctokit();
65const { data } = await octokit.issues.create({ owner, repo: repoName, title, body, labels });
src/connectors/github/tools.ts:63

// Exploitable if an attacker can influence the repo parameter. Since the MCP is network-exposed, an attacker can directly call these tools.

EXPLAINThe github_create_issue_confirmed and github_get_pr_status tools also accept a 'repo' parameter without validation beyond splitting on '/'. An attacker could provide a malicious repo string to create issues in unintended repositories or fetch PR status from arbitrary repos.
IMPACTAn attacker could create issues in any repository accessible by the authenticated GitHub user, or fetch PR status from repositories they should not have access to, potentially leaking information.
FIXValidate that the 'repo' parameter matches a strict pattern like /^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$/. Additionally, validate that the split results in exactly two non-empty parts.
6/10/2026
Findings are produced by automated LLM analysis and may include false positives or miss issues. Verify independently before acting.