| Titolo | feed-mob fm-mcp-servers Latest Server-Side Request Forgery |
|---|
| Descrizione | Summary
A Server-Side Request Forgery (SSRF) vulnerability exists in the @feedmob/smadex-reporting MCP server implementation (fm-mcp-servers monorepo).
The root cause is that the downloadUrl parameter in the get_smadex_report MCP tool is only validated as a plain string (z.string()) and then passed directly to fetch() inside downloadReport().
Because there is no destination allowlisting or network boundary validation, the server process can be induced to send HTTP requests to attacker-controlled or internal targets (for example localhost or private network services).
Details
The MCP server exposes get_smadex_report(downloadUrl: string) to download and return Smadex report CSV content from a remote URL.
Although the tool schema requires a string via Zod, it does not enforce URL format restrictions or destination restrictions.
This means attacker-controlled tool input can reach the HTTP request sink directly. The tool does not require Smadex authentication for the download step; only dummy SMADEX_EMAIL / SMADEX_PASSWORD values are needed for server startup.
Vulnerable Code
Version: 0.0.3
File: src/smadex-reporting/src/index.ts
async function downloadReport(url: string): Promise<string> {
try {
console.error(`Downloading report from URL: ${url}`);
const response = await fetch(url);
if (!response.ok) {
const errorBody = await response.text();
console.error(`Smadex Download Error: ${response.status} ${response.statusText} - ${errorBody}`);
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
}
const data = await response.text();
// ...
return cleanedData;
} catch (error: any) {
console.error(`Error downloading report:`, error);
throw new Error(`Failed to download report: ${error.message}`);
}
}
server.tool("get_smadex_report",
"Download and return report data from a Smadex report download URL.",
{
downloadUrl: z.string().describe("The download URL for the report")
}, async ({ downloadUrl }) => {
try {
console.error(`Downloading report from URL: ${downloadUrl}`);
const reportData = await downloadReport(downloadUrl);
return {
content: [
{
type: "text",
text: reportData
}
]
};
} catch (error: any) {
const errorMessage = `Error downloading report: ${error.message}`;
return {
content: [
{
type: "text",
text: errorMessage
}
],
isError: true
};
}
});
Current validation does not restrict:
destination hostname/domain
resolved IP range (loopback/private/link-local/metadata)
destination port
redirect targets
As a result, attacker-controlled downloadUrl input reaches the outbound request sink directly.
Data Flow (source → sink)
MCP client invokes tools/call for get_smadex_report with attacker-controlled downloadUrl.
MCP server receives downloadUrl argument in the get_smadex_report handler.
Server executes downloadReport(downloadUrl).
downloadReport() executes fetch(url).
Outbound request is sent from server network context to attacker-selected destination.
Response body is returned to the caller as tool output (full-read SSRF).
Malicious attackers can inject malicious tool parameters through methods such as prompt/message injection or hijacking MCP client behavior, thereby triggering SSRF.
Using MCP Inspector (Proof of Concept)
Prerequisites
Dependencies installed for @feedmob/smadex-reporting (npm install && npm run build in src/smadex-reporting)
MCP Inspector available (npx @modelcontextprotocol/inspector)
Local HTTP listener to capture requests
Placeholder Smadex env vars (required for server startup only; not used by this tool):
$env:SMADEX_API_BASE_URL = "https://example.com"
$env:SMADEX_EMAIL = "[email protected]"
$env:SMADEX_PASSWORD = "dummy"
Steps
Start a local receiver endpoint: python -m http.server 8000
Start Inspector with the vulnerable server (from src/smadex-reporting): npx @modelcontextprotocol/[email protected] node dist/index.js
In Inspector:
Select transport stdio
Command: node
Args: dist/index.js
Click Connect
Open Tools
Select get_smadex_report
Use payload: http://127.0.0.1:8000/ssrf-test
Click Run Tool
On the local receiver terminal (python -m http.server 8000), a new request appears (e.g. GET /ssrf-test), confirming SSRF.
Impact
Server-Side Request Forgery (SSRF). |
|---|
| Fonte | ⚠️ https://github.com/feed-mob/fm-mcp-servers/issues/198 |
|---|
| Utente | skywings (UID 98274) |
|---|
| Sottomissione | 25/06/2026 11:34 (2 mesi fa) |
|---|
| Moderazione | 13/08/2026 19:13 (2 months later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 389676 [feedmob fm-mcp-servers 0.0.3 Download Endpoint index.ts downloadReport downloadUrl escalationi di privilegi] |
|---|
| Punti | 20 |
|---|