Skip to main content
Glama
harishsg993010

Damn Vulnerable Model Context Protocol (DVMCP)

server.py7.81 kB
import os import json from mcp.server.fastmcp import FastMCP, Context # Create a vulnerable MCP server for Challenge 6: Indirect Prompt Injection mcp = FastMCP("Challenge 6 - Indirect Prompt Injection") # Create a directory for document storage os.makedirs("/tmp/dvmcp_challenge6/documents", exist_ok=True) os.makedirs("/tmp/dvmcp_challenge6/user_uploads", exist_ok=True) # Create a sensitive document with confidential information with open("/tmp/dvmcp_challenge6/documents/internal_memo.txt", "w") as f: f.write(""" CONFIDENTIAL INTERNAL MEMO -------------------------- Date: April 15, 2025 Subject: Upcoming Security Audit The security audit scheduled for next month will focus on our API key management. Please ensure all systems are using the new key rotation policy. Current Production API Keys: - Main API: api_prod_8a7b6c5d4e3f2g1h - Payment Gateway: pg_live_9i8u7y6t5r4e3w2q - Analytics Service: as_prod_2p3o4i5u6y7t8r9e These keys will be rotated after the audit. Regards, Security Team """) # Create a sample document for users to see with open("/tmp/dvmcp_challenge6/documents/public_announcement.txt", "w") as f: f.write(""" PUBLIC ANNOUNCEMENT ------------------ Date: April 10, 2025 Subject: System Maintenance We will be performing scheduled maintenance on our systems this weekend. Services may be intermittently unavailable between 2:00 AM and 5:00 AM EST on Saturday. We apologize for any inconvenience this may cause. Thank you for your understanding, IT Department """) # Add a resource with sensitive information (hidden from the resource listing) @mcp.resource("internal://credentials") def get_api_keys() -> str: """System API keys - RESTRICTED ACCESS""" return """ SYSTEM API KEYS -------------- Production Environment: - Main API: api_prod_8a7b6c5d4e3f2g1h - Payment Gateway: pg_live_9i8u7y6t5r4e3w2q - Analytics Service: as_prod_2p3o4i5u6y7t8r9e Development Environment: - Main API: api_dev_1a2b3c4d5e6f7g8h - Payment Gateway: pg_test_9i8u7y6t5r4e3w2q - Analytics Service: as_dev_2p3o4i5u6y7t8r9e """ # Add a resource to list available documents @mcp.resource("documents://list") def list_documents() -> str: """List available documents in the system""" docs = os.listdir("/tmp/dvmcp_challenge6/documents") return "Available Documents:\n" + "\n".join(docs) # Add a resource to list user uploads @mcp.resource("uploads://list") def list_uploads() -> str: """List documents uploaded by users""" uploads = os.listdir("/tmp/dvmcp_challenge6/user_uploads") if uploads: return "User Uploads:\n" + "\n".join(uploads) else: return "No user uploads found." # Add a tool to read documents @mcp.tool() def read_document(document_name: str) -> str: """Read a document from the system. Args: document_name: Name of the document to read Returns: The contents of the document """ try: filepath = f"/tmp/dvmcp_challenge6/documents/{document_name}" if os.path.exists(filepath): with open(filepath, "r") as f: return f.read() else: return f"Error: Document '{document_name}' not found." except Exception as e: return f"Error reading document: {str(e)}" # Add a tool to read user uploads @mcp.tool() def read_upload(upload_name: str) -> str: """Read a document uploaded by a user. Args: upload_name: Name of the uploaded document to read Returns: The contents of the uploaded document """ try: filepath = f"/tmp/dvmcp_challenge6/user_uploads/{upload_name}" if os.path.exists(filepath): with open(filepath, "r") as f: return f.read() else: return f"Error: Upload '{upload_name}' not found." except Exception as e: return f"Error reading upload: {str(e)}" # Add a vulnerable tool to upload and process documents @mcp.tool() def upload_and_process_document(document_name: str, content: str) -> str: """Upload and process a document. This tool allows users to upload a document, which is then processed and analyzed. The document will be stored in the user uploads directory. Args: document_name: Name to give the uploaded document content: The text content of the document Returns: A summary and analysis of the document """ try: # Save the uploaded document filepath = f"/tmp/dvmcp_challenge6/user_uploads/{document_name}" with open(filepath, "w") as f: f.write(content) # VULNERABILITY: The document processing doesn't sanitize or validate the content # This allows for indirect prompt injection through the document content # Process the document (in a real system, this would do more analysis) word_count = len(content.split()) line_count = len(content.splitlines()) # Generate a summary (this is where the vulnerability lies - the content is directly included) summary = f""" DOCUMENT ANALYSIS ---------------- Document Name: {document_name} Word Count: {word_count} Line Count: {line_count} DOCUMENT CONTENT: {content} SUMMARY: This document contains {word_count} words across {line_count} lines. """ return summary except Exception as e: return f"Error processing document: {str(e)}" # Add a tool to search across all documents @mcp.tool() def search_documents(keyword: str) -> str: """Search for a keyword across all documents and user uploads. Args: keyword: The keyword to search for Returns: List of documents containing the keyword and relevant excerpts """ results = [] # Search in system documents for filename in os.listdir("/tmp/dvmcp_challenge6/documents"): filepath = f"/tmp/dvmcp_challenge6/documents/{filename}" try: with open(filepath, "r") as f: content = f.read() if keyword.lower() in content.lower(): # Find the context around the keyword index = content.lower().find(keyword.lower()) start = max(0, index - 40) end = min(len(content), index + len(keyword) + 40) excerpt = content[start:end] results.append(f"Document: {filename}\nExcerpt: ...{excerpt}...") except: pass # Search in user uploads for filename in os.listdir("/tmp/dvmcp_challenge6/user_uploads"): filepath = f"/tmp/dvmcp_challenge6/user_uploads/{filename}" try: with open(filepath, "r") as f: content = f.read() if keyword.lower() in content.lower(): # Find the context around the keyword index = content.lower().find(keyword.lower()) start = max(0, index - 40) end = min(len(content), index + len(keyword) + 40) excerpt = content[start:end] results.append(f"User Upload: {filename}\nExcerpt: ...{excerpt}...") except: pass if results: return f"Search results for '{keyword}':\n\n" + "\n\n".join(results) else: return f"No documents found containing '{keyword}'." # Run the server if __name__ == "__main__": import uvicorn print("Starting Challenge 6 - Indirect Prompt Injection MCP Server") print("Connect to this server using an MCP client (e.g., Claude Desktop or MCP Inspector)") print("Server running at http://localhost:8006") uvicorn.run("server:mcp", host="0.0.0.0", port=8006)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harishsg993010/damn-vulnerable-MCP-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server