const SecurityManager = require('../src/security/security-manager'); describe('SecurityManager', () => { let securityManager; beforeEach(() => { securityManager = new SecurityManager(); }); describe('verifyIntegrity', () => { test('should verify valid integrity hash', async () => { const data = Buffer.from('test data'); const crypto = require('crypto'); const hash = crypto.createHash('sha256').update(data).digest('base64'); const integrity = `sha256-${hash}`; const result = await securityManager.verifyIntegrity(data, integrity); expect(result).toBe(true); }); test('should reject invalid integrity hash', async () => { const data = Buffer.from('test data'); const integrity = 'sha256-invalidhash'; await expect(securityManager.verifyIntegrity(data, integrity)) .rejects.toThrow('Package integrity verification failed'); }); test('should reject invalid integrity format', async () => { const data = Buffer.from('test data'); const integrity = 'invalid-format'; await expect(securityManager.verifyIntegrity(data, integrity)) .rejects.toThrow('Invalid integrity format'); }); test('should reject unsupported hash algorithm', async () => { const data = Buffer.from('test data'); const integrity = 'sha1-somehash'; // sha1 is not in allowedHashAlgorithms await expect(securityManager.verifyIntegrity(data, integrity)) .rejects.toThrow('Unsupported hash algorithm: sha1'); }); }); describe('checkPackageSize', () => { test('should allow packages under size limit', async () => { const smallData = Buffer.from('small package'); const result = await securityManager.checkPackageSize(smallData); expect(result).toBe(true); }); test('should reject packages over size limit', async () => { // Create a large buffer (larger than 100MB default limit) const largeSize = 101 * 1024 * 1024; // 101MB const largeData = Buffer.alloc(largeSize); await expect(securityManager.checkPackageSize(largeData)) .rejects.toThrow('Package size exceeds maximum allowed'); }); }); describe('checkBlockedPackages', () => { test('should allow non-blocked packages', async () => { const result = await securityManager.checkBlockedPackages('safe-package'); expect(result).toBe(true); }); test('should reject blocked packages', async () => { securityManager.securityConfig.blockedPackages.add('blocked-package'); await expect(securityManager.checkBlockedPackages('blocked-package')) .rejects.toThrow('Package "blocked-package" is blocked for security reasons'); }); }); describe('scanPackageContent', () => { test('should detect suspicious patterns', async () => { const suspiciousCode = Buffer.from(` const fs = require('fs'); eval('malicious code'); require('child_process').exec('rm -rf /'); `); const indicators = await securityManager.scanPackageContent(suspiciousCode, 'test-package'); expect(indicators.length).toBeGreaterThan(0); expect(indicators.some(i => i.pattern.includes('eval'))).toBe(true); }); test('should not flag clean code', async () => { const cleanCode = Buffer.from(` function add(a, b) { return a + b; } module.exports = { add }; `); const indicators = await securityManager.scanPackageContent(cleanCode, 'clean-package'); expect(indicators.length).toBe(0); }); test('should detect obfuscated code', async () => { const obfuscatedCode = Buffer.from(` var _0x1234567890abcdefghijklmnop = ['\\x65\\x76\\x61\\x6c']; function _0x1234567890abcdefghijklmnopqrstuvwxyz() { return _0x1234567890abcdefghijklmnop; } var _0x9abcdefghijklmnopqrstuvwxyz0123456789 = _0x1234567890abcdefghijklmnopqrstuvwxyz(); _0x9abcdefghijklmnopqrstuvwxyz0123456789[0]('\\u0061\\u006c\\u0065\\u0072\\u0074("test")'); unescape('%61%6c%65%72%74'); String.fromCharCode(97,108,101,114,116); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; `); const indicators = await securityManager.scanPackageContent(obfuscatedCode, 'obfuscated-package'); expect(indicators.length).toBeGreaterThan(0); }); }); describe('generatePackageHash', () => { test('should generate consistent hash', async () => { const data = Buffer.from('test data'); const hash1 = await securityManager.generatePackageHash(data); const hash2 = await securityManager.generatePackageHash(data); expect(hash1).toBe(hash2); expect(typeof hash1).toBe('string'); expect(hash1.length).toBeGreaterThan(0); }); test('should generate different hashes for different data', async () => { const data1 = Buffer.from('test data 1'); const data2 = Buffer.from('test data 2'); const hash1 = await securityManager.generatePackageHash(data1); const hash2 = await securityManager.generatePackageHash(data2); expect(hash1).not.toBe(hash2); }); }); describe('createIntegrityString', () => { test('should create valid integrity string', async () => { const data = Buffer.from('test data'); const integrity = await securityManager.createIntegrityString(data); expect(integrity).toMatch(/^sha512-.+$/); // Verify it can be used for verification const isValid = await securityManager.verifyIntegrity(data, integrity); expect(isValid).toBe(true); }); }); describe('assessPackageRisk', () => { test('should assess risk for new package', () => { const pkg = { name: 'new-package', time: { created: Date.now() - (20 * 24 * 60 * 60 * 1000) }, // 20 days ago downloads: { weekly: 50 }, maintainers: [] }; const scanResults = []; const risk = securityManager.assessPackageRisk(pkg, scanResults); expect(risk.score).toBeGreaterThan(0); expect(risk.level).toBe('high'); // Score is 5: 2 (new) + 2 (low downloads) + 1 (no maintainers) expect(risk.factors).toContain('Package is very new (< 30 days)'); expect(risk.factors).toContain('Low download count'); expect(risk.factors).toContain('No maintainers'); }); test('should assess lower risk for established package', () => { const pkg = { name: 'established-package', time: { created: Date.now() - (365 * 24 * 60 * 60 * 1000) }, // 1 year ago downloads: { weekly: 10000 }, maintainers: [{ name: 'maintainer1' }], dependencies: {} }; const scanResults = []; const risk = securityManager.assessPackageRisk(pkg, scanResults); expect(risk.score).toBe(0); expect(risk.level).toBe('low'); expect(risk.factors).toHaveLength(0); }); test('should increase risk for suspicious scan results', () => { const pkg = { name: 'suspicious-package', time: { created: Date.now() - (365 * 24 * 60 * 60 * 1000) }, downloads: { weekly: 1000 }, maintainers: [{ name: 'maintainer1' }] }; const scanResults = [ { severity: 'high' }, { severity: 'medium' } ]; const risk = securityManager.assessPackageRisk(pkg, scanResults); expect(risk.score).toBe(4); // 3 for high + 1 for medium expect(risk.level).toBe('high'); expect(risk.factors).toContain('2 suspicious patterns detected'); }); }); });