jaeyongk/quickchart-mcp-server-jykim
highNo description
This MCP server generates chart images using QuickChart.io's URL-based chart generation service. It provides tools to create chart URLs or download ch...
251case 'download_chart': {
252 try {
253 const { config, outputPath } = request.params.arguments as {
254 config: Record<string, unknown>;
255 outputPath: string;
256 };
257 const chartConfig = this.generateChartConfig(config);
258 const url = await this.generateChartUrl(chartConfig);
259
260 const response = await axios.get(url, { responseType: 'arraybuffer' });
261 const fs = await import('fs');
262 await fs.promises.writeFile(outputPath, response.data);
263
264 return {
265 content: [
266 {
267 type: 'text',
268 text: `Chart saved to ${outputPath}`
269 }
270 ]
271 };
272 } catch (error: any) {// Exploitable if MCP is exposed to untrusted prompts (network_exposed) or by a compromised LLM (local_only).
The download_chart tool accepts an arbitrary outputPath from the user without any validation or sanitization. This allows writing files to any location the process has access to, enabling path traversal attacks.
ImpactAn attacker (or compromised LLM) can write arbitrary files to the filesystem, potentially overwriting critical system files, planting malicious scripts, or modifying configuration files.
FixValidate and sanitize outputPath to ensure it is within an allowed directory (e.g., using path.resolve and checking against a whitelist of allowed directories). Use path.basename or restrict to a specific output folder.
144private async generateChartUrl(config: ChartConfig): Promise<string> {
145 const encodedConfig = encodeURIComponent(JSON.stringify(config));
146 return `${QUICKCHART_BASE_URL}?c=${encodedConfig}`;
147}// Exploitable if MCP is exposed to untrusted prompts (network_exposed) or by a compromised LLM (local_only).
The chart configuration is serialized and sent as a query parameter to QuickChart.io. While the base URL is fixed, the config object is fully user-controlled and can include arbitrary properties. This could be used to inject malicious parameters or trigger SSRF if QuickChart.io processes the config in unexpected ways (e.g., fetching external resources).
ImpactAn attacker could potentially exploit QuickChart.io's processing of the chart config to perform SSRF, data exfiltration, or other attacks against internal or external services.
FixValidate and sanitize the chart configuration to only allow expected properties. Consider using a strict schema validation that rejects unknown keys.
79private generateChartConfig(args: any): ChartConfig {
80 const { type, labels, datasets, title, options = {} } = args;
81
82 this.validateChartType(type);
83
84 const config: ChartConfig = {
85 type,
86 data: {
87 labels: labels || [],
88 datasets: datasets.map((dataset: any) => ({
89 label: dataset.label || '',
90 data: dataset.data,
91 backgroundColor: dataset.backgroundColor,
92 borderColor: dataset.borderColor,
93 ...dataset.additionalConfig
94 }))
95 },
96 options: {
97 ...options,
98 ...(title && {
99 title: {
100 display: true,
101 text: title
102 }
103 })
104 }
105 };// Exploitable if MCP is exposed to untrusted prompts (network_exposed) or by a compromised LLM (local_only).
The generateChartConfig method spreads user-controlled 'options' and 'additionalConfig' objects directly into the chart configuration without any validation. This allows an attacker to inject arbitrary properties into the JSON sent to QuickChart.io, potentially enabling SSRF or other attacks.
ImpactAn attacker can inject arbitrary JSON properties into the chart config, which may be interpreted by QuickChart.io to perform unintended actions (e.g., fetching external URLs, executing scripts).
FixUse a strict schema validation to only allow known properties in options and additionalConfig. Reject any unknown keys.