[ ⌘K ]
← BACK TO SEARCH

JordanDalton/composer-mcp-server

critical

Using AI, install Composer PHP packages with ease.

This MCP server provides an AI-powered interface for installing Composer PHP packages. It generates the appropriate composer require command, fetches ...

purpose: This MCP server provides an AI-powered interface fthreat: network exposed
TypeScript2May 20, 2026May 20, 2026GITHUB
5/20/2026
high1 finding
src/index.ts
144async function fetchPackageInfo(packageName: string): Promise<any> {
145    try {
146      const response = await axios.get(`https://packagist.org/packages/${packageName}.json`);
147      if (response.data && response.data.package) {
148        return response.data.package;
149      }
150      return null;
151    } catch (error) {
152      console.error(`Error fetching package info from Packagist: ${error}`);
153      return null;
154    }
155  }
src/index.ts:4src/index.ts:146

// Exploitable if MCP is exposed to untrusted prompts (network_exposed).

The package name from user input is directly interpolated into the URL for the Packagist API request without validation. An attacker could inject path traversal or special characters to make requests to arbitrary endpoints on packagist.org or potentially other hosts if the base URL is manipulated.

ImpactAn attacker could potentially access internal services or perform SSRF attacks by crafting a malicious package name that alters the URL path, though the domain is fixed to packagist.org. The risk is limited but present.

FixValidate the package name against a strict pattern (e.g., vendor/package format) before constructing the URL. Use URL encoding or a parameterized approach.

high1 finding
src/index.ts
158async function fetchGitHubReadme(repoUrl: string): Promise<string | null> {
159    try {
160      const match = repoUrl.match(/github\.com\/([^\/]+\/[^\/]+)/);
161      if (!match) return null;
162      
163      const repo = match[1];
164      const apiUrl = `https://api.github.com/repos/${repo}/readme`;
165      
166      const response = await axios.get(apiUrl, {
167        headers: {
168          'Accept': 'application/vnd.github.v3.raw'
169        }
170      });
171      
172      return response.data;
173    } catch (error) {
174      console.error(`Error fetching README from GitHub: ${error}`);
175      return null;
176    }
177  }
src/index.ts:4src/index.ts:162src/index.ts:166

// Exploitable if MCP is exposed to untrusted prompts (network_exposed).

The repository URL is extracted from Packagist data, which is indirectly user-controlled via the package name. The regex extraction is relatively safe, but if the repository URL from Packagist is manipulated (e.g., via a malicious package), it could lead to SSRF against GitHub API or other hosts.

ImpactAn attacker could potentially cause the server to make requests to arbitrary URLs if they can influence the repository URL returned by Packagist, though this requires control over a Packagist package.

FixValidate that the repository URL matches expected patterns and restrict to known domains. Consider caching or using a whitelist.

high1 finding
src/index.ts
182async function fetchGitLabReadme(repoUrl: string): Promise<string | null> {
183    try {
184      const match = repoUrl.match(/gitlab\.com\/([^\/]+\/[^\/]+)/);
185      if (!match) return null;
186      
187      const projectId = encodeURIComponent(match[1]);
188      const apiUrl = `https://gitlab.com/api/v4/projects/${projectId}/repository/files/README.md/raw`;
189      
190      const response = await axios.get(apiUrl);
191      return response.data;
192    } catch (error) {
193      console.error(`Error fetching README from GitLab: ${error}`);
194      return null;
195    }
196  }
src/index.ts:4src/index.ts:186src/index.ts:190

// Exploitable if MCP is exposed to untrusted prompts (network_exposed).

Similar to GitHub, the repository URL from Packagist is used to construct a GitLab API request. Although encodeURIComponent is used, the URL is still derived from user-controlled data, potentially allowing SSRF if the repository URL is malicious.

ImpactAn attacker could cause requests to arbitrary GitLab projects or potentially other hosts if the regex is bypassed.

FixValidate the repository URL against a strict pattern and restrict to known domains.

medium1 finding
src/index.ts
17server.tool("install_package",
18    {
19      package: z.string().describe("The package name to install"),
20      version: z.string().optional().describe("The version of the package to install")
21    },
src/index.ts:3src/index.ts:18

// Exploitable if MCP is exposed to untrusted prompts (network_exposed).

The package name is accepted as a free-form string without any validation (e.g., regex for vendor/package format). This allows injection of special characters that could affect URL construction or command generation.

ImpactAn attacker could provide a package name with path traversal characters or other payloads, potentially leading to SSRF or other injection attacks.

FixAdd Zod validation to enforce a pattern like /^[a-z0-9_-]+/[a-z0-9_-]+$/ for the package name.

network.httpshell.execenv.exposure
90
LLM-based
high findings+75
medium findings+15