nikto-mcp
Version:
A secure MCP (Model Context Protocol) server that enables AI agents to interact with Nikto web server scanner
121 lines (96 loc) • 3.83 kB
text/typescript
import { NiktoService } from '../src/services/nikto.service';
import { ScanStatus } from '../src/types/scan.types';
// Mock the logger to avoid console output during tests
jest.mock('../src/utils/logger', () => ({
createLogger: () => ({
info: jest.fn(),
debug: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
}),
}));
describe('NiktoService', () => {
let niktoService: NiktoService;
beforeEach(() => {
niktoService = new NiktoService();
});
describe('startScan with dry run', () => {
it('should generate correct command for basic scan', async () => {
const options = {
target: 'example.com',
dryRun: true,
};
const result = await niktoService.startScan(options);
expect(result.status).toBe(ScanStatus.COMPLETED);
expect(result.target).toBe('example.com');
// Verify the scan was stored
const status = niktoService.getScanStatus(result.scanId);
expect(status.status).toBe(ScanStatus.COMPLETED);
// The output should contain the dry run command
const scan = (niktoService as any).activeScans.get(result.scanId);
expect(scan.output[0]).toContain('DRY RUN (local mode): nikto -h example.com');
expect(scan.output[0]).toContain('-timeout 3600');
expect(scan.output[0]).toContain('-nointeractive');
});
it('should generate correct command with all options', async () => {
const options = {
target: 'https://example.com',
port: 8443,
ssl: true,
nolookup: true,
vhost: 'test.example.com',
timeout: 1800,
outputFormat: 'json' as const,
dryRun: true,
};
const result = await niktoService.startScan(options);
const scan = (niktoService as any).activeScans.get(result.scanId);
const command = scan.output[0];
expect(command).toContain('-h https://example.com');
expect(command).toContain('-p 8443');
expect(command).toContain('-ssl');
expect(command).toContain('-nolookup');
expect(command).toContain('-vhost test.example.com');
expect(command).toContain('-timeout 1800');
expect(command).toContain('-Format json');
expect(command).toContain('-nointeractive');
});
it('should generate correct command with nossl option', async () => {
const options = {
target: 'example.com',
nossl: true,
dryRun: true,
};
const result = await niktoService.startScan(options);
const scan = (niktoService as any).activeScans.get(result.scanId);
const command = scan.output[0];
expect(command).toContain('-nossl');
expect(command).not.toContain('-ssl');
});
it('should not include ssl or nossl when neither is specified', async () => {
const options = {
target: 'example.com',
dryRun: true,
};
const result = await niktoService.startScan(options);
const scan = (niktoService as any).activeScans.get(result.scanId);
const command = scan.output[0];
expect(command).not.toContain('-ssl');
expect(command).not.toContain('-nossl');
});
});
describe('getActiveScans', () => {
it('should return list of active scans', async () => {
const options1 = { target: 'example1.com', dryRun: true };
const options2 = { target: 'example2.com', dryRun: true };
await niktoService.startScan(options1);
await niktoService.startScan(options2);
const activeScans = niktoService.getActiveScans();
expect(activeScans).toHaveLength(2);
expect(activeScans[0].target).toBe('example1.com');
expect(activeScans[1].target).toBe('example2.com');
expect(activeScans[0].status).toBe(ScanStatus.COMPLETED);
expect(activeScans[1].status).toBe(ScanStatus.COMPLETED);
});
});
});