Skip to main content
Glama

MCP Shamash

enforcer.ts11.2 kB
import * as path from 'path'; import * as fs from 'fs/promises'; import CIDR from 'ip-cidr'; import * as YAML from 'yaml'; import type { ProjectScope, BoundaryValidation, NetworkDefinition, ServiceDefinition } from '../types/index.js'; export class BoundaryEnforcer { private projectScope: ProjectScope | null = null; private readonly BLOCKED_NETWORKS = [ '0.0.0.0/8', // Current network '10.0.0.0/8', // Private network (unless in project) '224.0.0.0/4', // Multicast '255.255.255.255/32', // Broadcast '169.254.0.0/16', // Link-local ]; private readonly BLOCKED_PORTS = [22, 3389, 445, 135, 139]; // Management ports private readonly SYSTEM_PATHS = ['/etc', '/usr', '/var', '/sys', '/proc']; async initialize(): Promise<void> { this.projectScope = await this.discoverProjectScope(); console.error('Boundary enforcer initialized with scope:', { projectRoot: this.projectScope.projectRoot, networks: this.projectScope.networks.length, services: this.projectScope.services.length, }); } private async discoverProjectScope(): Promise<ProjectScope> { const projectRoot = process.cwd(); const scope: ProjectScope = { projectRoot, networks: [], services: [], containers: [], allowedPaths: [`${projectRoot}/**/*`], deniedPaths: this.SYSTEM_PATHS, excludedRanges: [...this.BLOCKED_NETWORKS], allowedPorts: [], }; try { // 1. Docker Compose Discovery await this.discoverDockerCompose(scope); // 2. Kubernetes Discovery await this.discoverKubernetes(scope); // 3. Package.json Discovery (for Node.js apps) await this.discoverNodeApp(scope); // 4. Local Service Discovery await this.discoverLocalServices(scope); } catch (error) { console.error('Error discovering project scope:', error); } return scope; } private async discoverDockerCompose(scope: ProjectScope): Promise<void> { const composePaths = [ 'docker-compose.yml', 'docker-compose.yaml', 'compose.yml', 'compose.yaml', ]; for (const composePath of composePaths) { const fullPath = path.join(scope.projectRoot, composePath); try { const content = await fs.readFile(fullPath, 'utf-8'); const compose = YAML.parse(content) as any; // Extract networks if (compose.networks) { for (const [name, config] of Object.entries(compose.networks as any)) { const networkConfig = config as any; const networkDef: NetworkDefinition = { name: `${path.basename(scope.projectRoot)}_${name}`, subnet: networkConfig?.ipam?.config?.[0]?.subnet || '172.20.0.0/16', type: 'docker', internal: networkConfig?.internal || false, }; scope.networks.push(networkDef); } } // Extract services if (compose.services) { for (const [name, config] of Object.entries(compose.services as any)) { const serviceConfig = config as any; const ports: number[] = []; if (serviceConfig?.ports) { for (const portMapping of serviceConfig.ports) { const port = typeof portMapping === 'string' ? parseInt(portMapping.split(':')[0]) : portMapping; if (!isNaN(port)) ports.push(port); } } const serviceDef: ServiceDefinition = { name, network: `${path.basename(scope.projectRoot)}_default`, ports, internal: !serviceConfig?.ports || serviceConfig.ports.length === 0, }; scope.services.push(serviceDef); } } console.error(`Discovered Docker Compose: ${composePath}`); break; // Use first found compose file } catch (error) { // File doesn't exist or invalid, continue } } } private async discoverKubernetes(scope: ProjectScope): Promise<void> { const k8sPaths = ['k8s', 'kubernetes', '.kube']; for (const k8sPath of k8sPaths) { const fullPath = path.join(scope.projectRoot, k8sPath); try { const stats = await fs.stat(fullPath); if (stats.isDirectory()) { // TODO: Implement K8s manifest parsing console.error(`Found Kubernetes directory: ${k8sPath}`); // Add default cluster network scope.networks.push({ name: 'kubernetes-cluster', subnet: '10.244.0.0/16', // Default Kubernetes pod CIDR type: 'kubernetes', }); } } catch (error) { // Directory doesn't exist, continue } } } private async discoverNodeApp(scope: ProjectScope): Promise<void> { try { const packagePath = path.join(scope.projectRoot, 'package.json'); const content = await fs.readFile(packagePath, 'utf-8'); JSON.parse(content); // Validate JSON structure // Look for common development ports const devPorts = [3000, 3001, 8000, 8080, 8081, 5173, 4000]; scope.allowedPorts.push(...devPorts); console.error('Discovered Node.js project'); } catch (error) { // Not a Node.js project, continue } } private async discoverLocalServices(scope: ProjectScope): Promise<void> { // Add localhost ranges scope.networks.push({ name: 'localhost', subnet: '127.0.0.0/8', type: 'local', }); // Add common development ports const commonPorts = [ 80, 443, 3000, 3001, 8000, 8080, 8081, 5000, 5001, 5173, 4000, 9000 ]; scope.allowedPorts.push(...commonPorts); } async validatePath(targetPath: string): Promise<BoundaryValidation> { if (!this.projectScope) { throw new Error('Boundary enforcer not initialized'); } try { // Resolve path to absolute const absolutePath = path.resolve(targetPath); // Check if path is within project root const relativePath = path.relative(this.projectScope.projectRoot, absolutePath); if (relativePath.startsWith('..')) { return { allowed: false, reason: 'Path is outside project root', violations: ['PATH_ESCAPE'], }; } // Check against denied paths for (const deniedPath of this.projectScope.deniedPaths) { if (absolutePath.startsWith(deniedPath)) { return { allowed: false, reason: `Path is in denied system directory: ${deniedPath}`, violations: ['SYSTEM_PATH_ACCESS'], }; } } // Check if path exists (optional - create if scanning) try { await fs.access(absolutePath); } catch (error) { // Path doesn't exist - this might be OK for scanning console.error(`Warning: Path does not exist: ${absolutePath}`); } return { allowed: true }; } catch (error) { return { allowed: false, reason: `Path validation error: ${error instanceof Error ? error.message : 'Unknown error'}`, violations: ['VALIDATION_ERROR'], }; } } async validateNetwork(target: string): Promise<BoundaryValidation> { if (!this.projectScope) { throw new Error('Boundary enforcer not initialized'); } try { // Parse target (could be IP, CIDR, or hostname) let targetIP: string; if (target === 'localhost' || target === '127.0.0.1') { targetIP = '127.0.0.1'; } else if (target.includes('/')) { // CIDR notation const cidr = new CIDR(target); targetIP = cidr.addressStart.address; } else if (target.match(/^\d+\.\d+\.\d+\.\d+$/)) { // IP address targetIP = target; } else { return { allowed: false, reason: 'Hostname resolution not allowed - use IP addresses only', violations: ['HOSTNAME_NOT_ALLOWED'], }; } // Check if IP is in blocked ranges for (const blockedRange of this.BLOCKED_NETWORKS) { const cidr = new CIDR(blockedRange); if (cidr.contains(targetIP)) { return { allowed: false, reason: `Target IP is in blocked range: ${blockedRange}`, violations: ['BLOCKED_NETWORK'], }; } } // Check if IP is in allowed project networks for (const network of this.projectScope.networks) { const cidr = new CIDR(network.subnet); if (cidr.contains(targetIP)) { return { allowed: true, scope: network }; } } return { allowed: false, reason: 'Target is not in any project network', violations: ['OUT_OF_SCOPE'], }; } catch (error) { return { allowed: false, reason: `Network validation error: ${error instanceof Error ? error.message : 'Unknown error'}`, violations: ['VALIDATION_ERROR'], }; } } async validateUrl(url: string): Promise<BoundaryValidation> { try { const urlObj = new URL(url); // Extract hostname and port const hostname = urlObj.hostname; const port = urlObj.port ? parseInt(urlObj.port) : (urlObj.protocol === 'https:' ? 443 : 80); // Check if port is blocked if (this.BLOCKED_PORTS.includes(port)) { return { allowed: false, reason: `Port ${port} is blocked for security`, violations: ['BLOCKED_PORT'], }; } // Validate the hostname as a network target return await this.validateNetwork(hostname); } catch (error) { return { allowed: false, reason: `Invalid URL: ${error instanceof Error ? error.message : 'Unknown error'}`, violations: ['INVALID_URL'], }; } } async validatePort(port: number): Promise<BoundaryValidation> { if (this.BLOCKED_PORTS.includes(port)) { return { allowed: false, reason: `Port ${port} is blocked for security (management port)`, violations: ['BLOCKED_PORT'], }; } if (port < 1 || port > 65535) { return { allowed: false, reason: 'Port number out of valid range (1-65535)', violations: ['INVALID_PORT'], }; } return { allowed: true }; } getProjectScope(): ProjectScope | null { return this.projectScope; } async logViolation(type: string, target: string, details?: any): Promise<void> { const violation = { timestamp: new Date().toISOString(), type, target, details, projectRoot: this.projectScope?.projectRoot, }; console.error('BOUNDARY VIOLATION:', JSON.stringify(violation, null, 2)); // TODO: Send to audit logger and/or SIEM } }

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/NeoTecDigital/mcp_shamash'

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