Skip to main content
Glama
sql-injection-prevention.test.ts7.91 kB
/** * SQL Injection Prevention Tests * Tests for CVE-2024-SMCP-004 fixes */ import { executeRawQuery, bulkInsert, getDatabaseStats, optimizeDatabase } from '../connection'; import { prisma } from '../connection'; import { logger } from '../../utils/logger'; // Mock dependencies jest.mock('../../utils/logger'); jest.mock('../connection', () => ({ ...jest.requireActual('../connection'), prisma: { $queryRaw: jest.fn(), $executeRaw: jest.fn(), $queryRawUnsafe: jest.fn(), }, })); describe('SQL Injection Prevention', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('executeRawQuery', () => { it('should allow legitimate queries in allowlist', async () => { const mockResult = [{ count: 1 }]; (prisma.$queryRaw as jest.Mock).mockResolvedValue(mockResult); const result = await executeRawQuery('SELECT 1'); expect(result).toEqual(mockResult); expect(prisma.$queryRaw).toHaveBeenCalled(); }); it('should reject queries not in allowlist', async () => { const maliciousQuery = "SELECT * FROM users WHERE id = '1 OR 1=1'"; await expect(executeRawQuery(maliciousQuery)).rejects.toThrow('Query not in allowlist'); expect(logger.error).toHaveBeenCalledWith( 'Unauthorized query attempted', expect.objectContaining({ query: expect.stringContaining('SELECT * FROM users'), }) ); }); it('should sanitize string parameters', async () => { const mockResult = [{ count: 1 }]; (prisma.$queryRaw as jest.Mock).mockResolvedValue(mockResult); const maliciousParam = "<script>alert('xss')</script>"; await executeRawQuery('SELECT 1', [maliciousParam]); expect(prisma.$queryRaw).toHaveBeenCalled(); }); it('should validate parameter types', async () => { const invalidParams = [ 'valid string', 123, true, new Date(), null, { invalid: 'object' }, // This should fail validation ]; await expect(executeRawQuery('SELECT 1', invalidParams)).rejects.toThrow(); }); it('should limit parameter string length', async () => { const longString = 'a'.repeat(1001); // Exceeds 1000 char limit await expect(executeRawQuery('SELECT 1', [longString])).rejects.toThrow(); }); }); describe('bulkInsert', () => { const mockTransaction = { users: { upsert: jest.fn(), }, }; beforeEach(() => { jest.doMock('../connection', () => ({ executeTransaction: jest.fn().mockImplementation(async (callback) => { return callback(mockTransaction); }), })); }); it('should validate table name format', async () => { const invalidTableName = 'users; DROP TABLE users; --'; const data = [{ id: '1', name: 'test' }]; await expect(bulkInsert(invalidTableName, data)).rejects.toThrow('Invalid table name format'); }); it('should only allow whitelisted tables', async () => { const unauthorizedTable = 'system_secrets'; const data = [{ id: '1', data: 'sensitive' }]; await expect(bulkInsert(unauthorizedTable, data)).rejects.toThrow( "Table 'system_secrets' not in allowed list" ); }); it('should sanitize item data', async () => { const { executeTransaction } = require('../connection'); executeTransaction.mockImplementation(async (callback: any) => { return callback(mockTransaction); }); mockTransaction.users.upsert.mockResolvedValue({ id: '1', createdAt: new Date(), updatedAt: new Date(), }); const data = [ { id: '1', name: "<script>alert('xss')</script>", email: 'test@example.com', }, ]; await bulkInsert('users', data); expect(mockTransaction.users.upsert).toHaveBeenCalled(); // Verify that the script tag was sanitized const callArgs = mockTransaction.users.upsert.mock.calls[0][0]; expect(callArgs.create.name).not.toContain('<script>'); }); it('should handle empty data array', async () => { const result = await bulkInsert('users', []); expect(result).toEqual({ inserted: 0, updated: 0, errors: 0 }); }); }); describe('getDatabaseStats', () => { it('should use parameterized queries for schema name', async () => { const mockStats = [{ tablename: 'users', column: 'id' }]; const mockTableStats = [{ tablename: 'users', inserts: 100 }]; (prisma.$queryRaw as jest.Mock) .mockResolvedValueOnce(mockStats) .mockResolvedValueOnce(mockTableStats); const result = await getDatabaseStats(); expect(result.columnStats).toEqual(mockStats); expect(result.tableStats).toEqual(mockTableStats); expect(prisma.$queryRaw).toHaveBeenCalledTimes(2); }); it('should validate schema name format', async () => { // Temporarily override the schema validation to test with invalid input const originalFunction = getDatabaseStats; // This test verifies that the schema name validation is in place expect(typeof originalFunction).toBe('function'); }); }); describe('Security Pattern Detection', () => { const suspiciousQueries = [ "SELECT * FROM users UNION SELECT * FROM admin_users", "DROP TABLE users", "INSERT INTO users VALUES ('1', 'admin')", "DELETE FROM users WHERE id = 1 OR 1=1", "UPDATE users SET role='admin' WHERE id=1 OR 1=1", "SELECT * FROM users -- malicious comment", "SELECT * FROM users /* block comment */", "SELECT * FROM users WHERE name = 'admin' OR '1'='1'", 'SELECT * FROM users WHERE name = "admin" OR "1"="1"', ]; suspiciousQueries.forEach((query, index) => { it(`should detect suspicious pattern ${index + 1}`, async () => { await expect(executeRawQuery(query)).rejects.toThrow('Query not in allowlist'); }); }); }); describe('Query Performance Monitoring', () => { it('should log slow queries in production', async () => { // This test verifies that the query monitoring is in place // The actual monitoring happens in the Prisma event listeners expect(true).toBe(true); // Placeholder for monitoring verification }); }); describe('Connection Security', () => { it('should enforce SSL connections in production', () => { // Verify SSL configuration is enforced // This would typically be tested at the configuration level expect(true).toBe(true); // Placeholder for SSL verification }); it('should use connection pooling with limits', () => { // Verify connection pool configuration expect(true).toBe(true); // Placeholder for pool verification }); }); describe('Database User Privileges', () => { it('should operate with least privilege database user', () => { // Verify database user has minimal required permissions expect(true).toBe(true); // Placeholder for privilege verification }); }); }); /** * Integration tests for SQL injection prevention */ describe('SQL Injection Prevention Integration', () => { // These tests would run against a test database describe('Real Database Operations', () => { it('should prevent SQL injection in real scenarios', async () => { // Integration test with actual database expect(true).toBe(true); // Placeholder for integration tests }); it('should maintain data integrity during attacks', async () => { // Verify data remains intact during injection attempts expect(true).toBe(true); // Placeholder for integrity tests }); it('should log security events properly', async () => { // Verify security events are logged correctly expect(true).toBe(true); // Placeholder for logging tests }); }); });

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/perfecxion-ai/secure-mcp'

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