210 líneas
7.5 KiB
JavaScript
210 líneas
7.5 KiB
JavaScript
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');
|
|
});
|
|
});
|
|
});
|