Skip to main content
Glama

Claude MCP Server Integration

by mokemoke0821
security.test.ts10.5 kB
import { describe, expect, it, beforeEach, vi } from 'vitest' import { SecurityUtils } from './security' // 🧪 SecurityUtils エンタープライズ品質テスト describe('SecurityUtils', () => { beforeEach(() => { vi.clearAllMocks() }) describe('🔒 HTML Sanitization', () => { it('should sanitize malicious HTML content', () => { const maliciousInput = '<script>alert("xss")</script><p>Safe content</p>' const result = SecurityUtils.sanitizeHtml(maliciousInput) expect(result).not.toContain('<script>') expect(result).toContain('<p>Safe content</p>') }) it('should allow safe HTML tags', () => { const safeInput = '<p><strong>Bold</strong> and <em>italic</em> text</p>' const result = SecurityUtils.sanitizeHtml(safeInput) expect(result).toBe(safeInput) }) it('should remove dangerous attributes', () => { const dangerousInput = '<p onclick="alert(\'xss\')">Click me</p>' const result = SecurityUtils.sanitizeHtml(dangerousInput) expect(result).not.toContain('onclick') expect(result).toContain('<p>Click me</p>') }) it('should strip comments', () => { const inputWithComments = '<p>Content</p><!-- malicious comment -->' const result = SecurityUtils.sanitizeHtml(inputWithComments) expect(result).not.toContain('<!--') expect(result).toContain('<p>Content</p>') }) }) describe('🔍 Input Validation', () => { it('should validate string inputs correctly', () => { expect(SecurityUtils.validateInput('valid string')).toBe(true) expect(SecurityUtils.validateInput('')).toBe(false) expect(SecurityUtils.validateInput(null)).toBe(false) expect(SecurityUtils.validateInput(undefined)).toBe(false) expect(SecurityUtils.validateInput(123)).toBe(false) }) it('should reject extremely long strings', () => { const longString = 'a'.repeat(10001) expect(SecurityUtils.validateInput(longString)).toBe(false) }) it('should accept strings within limit', () => { const validString = 'a'.repeat(1000) expect(SecurityUtils.validateInput(validString)).toBe(true) }) }) describe('🚫 SQL Injection Prevention', () => { it('should remove SQL injection patterns', () => { const sqlInjection = "'; DROP TABLE users; --" const result = SecurityUtils.sanitizeSQLInput(sqlInjection) expect(result).not.toContain("'") expect(result).not.toContain(';') expect(result).not.toContain('DROP') expect(result).not.toContain('--') }) it('should remove SQL keywords', () => { const sqlKeywords = 'SELECT * FROM users UNION SELECT password' const result = SecurityUtils.sanitizeSQLInput(sqlKeywords) expect(result.toLowerCase()).not.toContain('select') expect(result.toLowerCase()).not.toContain('union') }) it('should preserve safe content', () => { const safeInput = 'John Doe' const result = SecurityUtils.sanitizeSQLInput(safeInput) expect(result).toBe('John Doe') }) }) describe('📧 Email Validation', () => { it('should validate correct email addresses', () => { expect(SecurityUtils.validateEmail('user@example.com')).toBe(true) expect(SecurityUtils.validateEmail('test.email+tag@domain.co.uk')).toBe(true) }) it('should reject invalid email addresses', () => { expect(SecurityUtils.validateEmail('invalid-email')).toBe(false) expect(SecurityUtils.validateEmail('user@')).toBe(false) expect(SecurityUtils.validateEmail('@domain.com')).toBe(false) expect(SecurityUtils.validateEmail('')).toBe(false) }) it('should reject extremely long email addresses', () => { const longEmail = 'a'.repeat(300) + '@example.com' expect(SecurityUtils.validateEmail(longEmail)).toBe(false) }) }) describe('🔐 Password Validation', () => { it('should validate strong passwords', () => { const strongPassword = 'StrongP@ssw0rd!' const result = SecurityUtils.validatePassword(strongPassword) expect(result.isValid).toBe(true) expect(result.errors).toHaveLength(0) }) it('should reject weak passwords', () => { const weakPassword = 'weak' const result = SecurityUtils.validatePassword(weakPassword) expect(result.isValid).toBe(false) expect(result.errors.length).toBeGreaterThan(0) }) it('should require minimum length', () => { const shortPassword = 'Sh0rt!' const result = SecurityUtils.validatePassword(shortPassword) expect(result.isValid).toBe(false) expect(result.errors).toContain('パスワードは8文字以上である必要があります') }) it('should require uppercase letters', () => { const noUppercase = 'lowercase123!' const result = SecurityUtils.validatePassword(noUppercase) expect(result.isValid).toBe(false) expect(result.errors).toContain('大文字を含める必要があります') }) it('should require special characters', () => { const noSpecial = 'Password123' const result = SecurityUtils.validatePassword(noSpecial) expect(result.isValid).toBe(false) expect(result.errors).toContain('特殊文字を含める必要があります') }) }) describe('🌐 URL Validation', () => { it('should validate correct URLs', () => { expect(SecurityUtils.validateUrl('https://example.com')).toBe(true) expect(SecurityUtils.validateUrl('http://localhost:3000')).toBe(true) }) it('should reject invalid URLs', () => { expect(SecurityUtils.validateUrl('not-a-url')).toBe(false) expect(SecurityUtils.validateUrl('ftp://example.com')).toBe(false) expect(SecurityUtils.validateUrl('javascript:alert(1)')).toBe(false) }) it('should require protocol', () => { expect(SecurityUtils.validateUrl('example.com')).toBe(false) }) }) describe('🔢 Number Validation', () => { it('should validate numbers correctly', () => { expect(SecurityUtils.validateNumber(42)).toBe(true) expect(SecurityUtils.validateNumber(0)).toBe(true) expect(SecurityUtils.validateNumber(-10)).toBe(true) }) it('should reject non-numbers', () => { expect(SecurityUtils.validateNumber('42')).toBe(false) expect(SecurityUtils.validateNumber(null)).toBe(false) expect(SecurityUtils.validateNumber(undefined)).toBe(false) expect(SecurityUtils.validateNumber(NaN)).toBe(false) expect(SecurityUtils.validateNumber(Infinity)).toBe(false) }) it('should validate number ranges', () => { expect(SecurityUtils.validateNumber(5, 1, 10)).toBe(true) expect(SecurityUtils.validateNumber(0, 1, 10)).toBe(false) expect(SecurityUtils.validateNumber(15, 1, 10)).toBe(false) }) }) describe('🆔 UUID Validation', () => { it('should validate correct UUIDs', () => { const validUUID = '123e4567-e89b-12d3-a456-426614174000' expect(SecurityUtils.validateUUID(validUUID)).toBe(true) }) it('should reject invalid UUIDs', () => { expect(SecurityUtils.validateUUID('invalid-uuid')).toBe(false) expect(SecurityUtils.validateUUID('123-456-789')).toBe(false) expect(SecurityUtils.validateUUID('')).toBe(false) }) }) describe('📱 JSON Sanitization', () => { it('should parse and sanitize valid JSON', () => { const validJSON = '{"name": "John", "message": "<script>alert(1)</script>"}' const result = SecurityUtils.sanitizeJSON(validJSON) expect(result).toBeTruthy() expect((result as any).name).toBe('John') expect((result as any).message).not.toContain('<script>') }) it('should reject invalid JSON', () => { const invalidJSON = '{"invalid": json}' const result = SecurityUtils.sanitizeJSON(invalidJSON) expect(result).toBeNull() }) it('should reject deeply nested objects', () => { const deepObject = JSON.stringify({ level1: { level2: { level3: { level4: { level5: { level6: { level7: { level8: { level9: { level10: { level11: 'too deep' } } } } } } } } } } }) const result = SecurityUtils.sanitizeJSON(deepObject) expect(result).toBeNull() }) }) describe('⏱️ Rate Limiting', () => { it('should allow requests within limit', () => { const identifier = 'test-user' for (let i = 0; i < 5; i++) { expect(SecurityUtils.checkRateLimit(identifier, 10, 60000)).toBe(true) } }) it('should block requests exceeding limit', () => { const identifier = 'rate-limited-user' // 制限まで到達 for (let i = 0; i < 3; i++) { SecurityUtils.checkRateLimit(identifier, 3, 60000) } // 制限を超える expect(SecurityUtils.checkRateLimit(identifier, 3, 60000)).toBe(false) }) it('should reset after time window', () => { const identifier = 'time-window-user' // 制限まで到達 for (let i = 0; i < 2; i++) { SecurityUtils.checkRateLimit(identifier, 2, 100) } // 時間経過をシミュレート vi.advanceTimersByTime(150) // 再度許可される expect(SecurityUtils.checkRateLimit(identifier, 2, 100)).toBe(true) }) }) describe('🛡️ CSP Nonce Generation', () => { it('should generate valid nonce', () => { const nonce = SecurityUtils.generateCSPNonce() expect(nonce).toBeTruthy() expect(typeof nonce).toBe('string') expect(nonce.length).toBe(32) // 16 bytes * 2 hex chars expect(/^[a-f0-9]+$/.test(nonce)).toBe(true) }) it('should generate unique nonces', () => { const nonce1 = SecurityUtils.generateCSPNonce() const nonce2 = SecurityUtils.generateCSPNonce() expect(nonce1).not.toBe(nonce2) }) }) describe('🔐 Session Validation', () => { it('should validate correct session IDs', () => { const validSessionId = '123e4567-e89b-12d3-a456-426614174000' expect(SecurityUtils.validateSession(validSessionId)).toBe(true) }) it('should reject invalid session IDs', () => { expect(SecurityUtils.validateSession('invalid-session')).toBe(false) expect(SecurityUtils.validateSession('')).toBe(false) expect(SecurityUtils.validateSession('123-456')).toBe(false) }) }) })

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/mokemoke0821/claude-mcp-integration'

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