arikusi/nakkas
criticalMCP server that turns AI into an SVG artist
This MCP server enables AI to generate animated SVG graphics from JSON configurations. It provides tools to render SVG, preview as PNG, and save to di...
266async ({ content, outputPath, format, width }) => {
267 const start = Date.now();
268 try {
269 const savedPath = await saveContent(content, outputPath, format, width);
270 const elapsed = Date.now() - start;
271 console.error(`[nakkas] save OK — ${savedPath}, ${elapsed}ms`);
272 return {
273 content: [{ type: "text", text: `Saved to: ${savedPath}` }],
274 };
275 } catch (err) {
276 const message = err instanceof Error ? err.message : String(err);
277 console.error(`[nakkas] save ERROR — ${message}`);
278 return {
279 content: [{ type: "text", text: `Error saving file: ${message}` }],
280 isError: true,
281 };
282 }
283 }266async ({ content, outputPath, format, width }) => {
267 const start = Date.now();
268 try {
269 const savedPath = await saveContent(content, outputPath, format, width);
270 const elapsed = Date.now() - start;
271 console.error(`[nakkas] save OK — ${savedPath}, ${elapsed}ms`);
272 return {
273 content: [{ type: "text", text: `Saved to: ${savedPath}` }],
274 };
275 } catch (err) {// Local-only MCP, requires compromised LLM to exploit. However, if the MCP is exposed to untrusted prompts (e.g., via a network-facing interface), this becomes a high-severity file write vulnerability.
The save tool accepts an outputPath parameter from the user without validating that it stays within an intended directory. The description says 'The directory must already exist' but does not restrict the path. An attacker could use path traversal sequences (e.g., '../') to write files outside the intended workspace, potentially overwriting system files or writing to sensitive locations.
ImpactAn attacker could write arbitrary SVG or PNG files to any location the server process has write access to, potentially overwriting configuration files, scripts, or other critical data.
FixValidate that outputPath resolves to a path within a designated output directory. Use path.resolve and check that the resolved path starts with the allowed base directory. Reject paths containing '..' or absolute paths if not intended.
189async ({ content, format, width }) => {
190 const start = Date.now();
191 try {
192 const pngBuffer = renderPreview(content, format, width);
193 const base64 = pngBuffer.toString("base64");
194 const elapsed = Date.now() - start;
195 console.error(`[nakkas] preview OK — ${pngBuffer.length} bytes, ${elapsed}ms`);
196 return {
197 content: [{ type: "image", data: base64, mimeType: "image/png" }],
198 };// Local-only MCP, requires compromised LLM to exploit. Denial of service could affect the local system.
The preview and save tools accept a 'content' string without any size limits. An attacker could provide an extremely large SVG string, causing excessive memory usage or disk writes, leading to denial of service.
ImpactAn attacker could cause the server to consume excessive memory or disk space, potentially crashing the process or filling up storage.
FixAdd a maximum length check on the content string (e.g., reject if > 10 MB). Also consider limiting the output file size in the save tool.
189async ({ content, format, width }) => {
190 const start = Date.now();
191 try {
192 const pngBuffer = renderPreview(content, format, width);
193 const base64 = pngBuffer.toString("base64");
194 const elapsed = Date.now() - start;
195 console.error(`[nakkas] preview OK — ${pngBuffer.length} bytes, ${elapsed}ms`);
196 return {
197 content: [{ type: "image", data: base64, mimeType: "image/png" }],
198 };
199 } catch (err) {
200 const message = err instanceof Error ? err.message : String(err);
201 console.error(`[nakkas] preview ERROR — ${message}`);
202 return {
203 content: [{ type: "text", text: `Error rendering preview: ${message}` }],
204 isError: true,
205 };
206 }
207 }// Local-only MCP, requires compromised LLM to exploit. Severity reduced from medium to low.
The preview tool accepts an SVG string and renders it to PNG. If the SVG contains external references (e.g., <image href="http://..."> or <use href="...">), the rendering engine may fetch those resources, leading to server-side request forgery (SSRF) or resource exhaustion. Additionally, a malicious SVG could cause denial of service via billion laughs attack or other XML bombs.
ImpactA compromised LLM could cause the server to make outbound requests to internal or external hosts, potentially exfiltrating data or scanning networks. Also could cause high CPU/memory usage.
FixSanitize SVG content before rendering: strip external references, disable external entity resolution, and set resource limits (e.g., max size, timeout). Use a secure SVG parser that disables network access.