Skip to main content
Glama
pshempel

MCP Time Server Node

by pshempel
mcp-attack-vectors.test.ts10.4 kB
import { describe, it, expect } from '@jest/globals'; import { createTestEnvironment } from '../integration/helpers/setup'; import { callTool } from '../integration/helpers/tools'; describe('MCP Security Tests - Attack Vectors', () => { afterEach(() => { // Clear any lingering timers after each test jest.clearAllTimers(); }); describe('Path Traversal Attacks', () => { it('should reject path traversal in date parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_business_days', { start_date: '../../../etc/passwd', end_date: '2025-01-05', }) ).rejects.toThrow(); } finally { await cleanup(); } }); it('should reject path traversal in timezone parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_current_time', { timezone: '../../etc/passwd', }) ).rejects.toThrow(/timezone/i); } finally { await cleanup(); } }); }); describe('SQL Injection Attacks', () => { it('should reject SQL injection in timezone', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_current_time', { timezone: "'; DROP TABLE users; --", }) ).rejects.toThrow(/timezone/i); } finally { await cleanup(); } }); it('should reject SQL injection in date parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'add_time', { time: "2025-01-01'; DELETE FROM holidays; --", amount: 1, unit: 'days', }) ).rejects.toThrow(); } finally { await cleanup(); } }); }); describe('XSS Attacks', () => { it('should sanitize XSS attempts in format strings', async () => { const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'get_current_time', { format: "<script>alert('xss')</script>", }); // Should either error or return safe output if (result.time) { expect(result.time).not.toContain('<script>'); expect(result.time).not.toContain('alert'); } } catch (error) { // Error is acceptable for invalid format expect(error).toBeDefined(); } finally { await cleanup(); } }); it('should reject XSS in timezone parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'convert_timezone', { time: '2025-01-01T12:00:00', from_timezone: '<img src=x onerror=alert(1)>', to_timezone: 'UTC', }) ).rejects.toThrow(/timezone/i); } finally { await cleanup(); } }); }); describe('Command Injection Attacks', () => { it('should reject command injection via timezone', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_current_time', { timezone: 'UTC; cat /etc/passwd', }) ).rejects.toThrow(/timezone/i); } finally { await cleanup(); } }); it('should safely handle command injection in format strings', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'format_time', { time: '2025-01-01T12:00:00', format: 'custom', custom_format: "'; cat /etc/passwd; echo '", }) ).rejects.toThrow(); } finally { await cleanup(); } }); }); describe('DoS Attack Vectors', () => { it('should handle extremely long timezone strings', async () => { const { client, cleanup } = await createTestEnvironment(); try { const longString = 'A'.repeat(10000); await expect( callTool(client, 'get_current_time', { timezone: longString, }) ).rejects.toThrow(); } finally { await cleanup(); } }); it('should handle extremely large date ranges', async () => { // This test simulates a DoS attack by requesting 9000 years of business days // The function SHOULD handle this gracefully (either with timeout or range limit) // This is a legitimate security test - attackers WILL try this! const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'get_business_days', { start_date: '1000-01-01', end_date: '9999-12-31', }); // Should either handle gracefully or error if (result.business_days) { expect(typeof result.business_days).toBe('number'); } } catch (error) { // Error for unreasonable range is acceptable expect(error).toBeDefined(); } finally { await cleanup(); } }, 60000); // 60 second timeout for this DoS simulation test it('should handle large holiday arrays', async () => { const { client, cleanup } = await createTestEnvironment(); try { const largeHolidayArray = new Array(10000).fill('2025-01-15'); const result = await callTool(client, 'get_business_days', { start_date: '2025-01-01', end_date: '2025-01-31', holidays: largeHolidayArray, }); // Should handle gracefully expect(result.business_days).toBeDefined(); } catch (error) { // Error for too many holidays is acceptable expect(error).toBeDefined(); } finally { await cleanup(); } }); }); describe('Prototype Pollution Attacks', () => { it('should ignore __proto__ in parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'get_business_days', { start_date: '2025-01-01', end_date: '2025-01-31', __proto__: { polluted: true }, } as any); // Should work normally, ignoring __proto__ expect(result.business_days).toBeDefined(); expect((Object.prototype as any).polluted).toBeUndefined(); } finally { await cleanup(); } }); it('should ignore constructor.prototype in parameters', async () => { const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'add_time', { time: '2025-01-01', amount: 1, unit: 'days', constructor: { prototype: { polluted: true } }, } as any); // Should work normally expect(result).toBeDefined(); expect((Object.prototype as any).polluted).toBeUndefined(); } finally { await cleanup(); } }); }); describe('Invalid Input Handling', () => { it('should handle null timezone gracefully', async () => { const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'get_current_time', { timezone: null as any, }); // Should use default timezone expect(result.time).toBeDefined(); expect(result.timezone).toBeDefined(); } finally { await cleanup(); } }); it('should reject non-string date inputs', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'add_time', { time: { toString: () => '2025-01-01' } as any, amount: 1, unit: 'days', }) ).rejects.toThrow(); } finally { await cleanup(); } }); it('should handle negative amount overflow', async () => { const { client, cleanup } = await createTestEnvironment(); try { const result = await callTool(client, 'add_time', { time: '2025-01-01', amount: -999999999999, unit: 'days', }); // Should either handle or error gracefully if (result) { expect(result).toBeDefined(); } } catch (error) { expect(error).toBeDefined(); } finally { await cleanup(); } }); it('should validate unit types strictly', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'add_time', { time: '2025-01-01', amount: 1, unit: "'; DROP TABLE; --" as any, }) ).rejects.toThrow(/unit/i); } finally { await cleanup(); } }); }); describe('Cache Key Attacks', () => { it('should sanitize cache keys with null bytes', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_current_time', { timezone: 'UTC\x00extra', }) ).rejects.toThrow(); } finally { await cleanup(); } }); it('should reject cache keys with path traversal', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_current_time', { timezone: 'UTC/../../../etc', }) ).rejects.toThrow(/timezone/i); } finally { await cleanup(); } }); it('should prevent cache poisoning attempts', async () => { const { client, cleanup } = await createTestEnvironment(); try { await expect( callTool(client, 'get_business_days', { start_date: '2025-01-01', end_date: '2025-01-31', holiday_calendar: 'US\x00admin', }) ).rejects.toThrow(); } finally { await cleanup(); } }); }); });

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/pshempel/mcp-time-server-node'

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