Files
n8n-enterprise-unlocked/packages/cli/src/commands/audit.ts
T
कारतोफ्फेलस्क्रिप्ट™ 9f8d3d3bc8 refactor(core): Overhaul commands setup. Add support for module commands (#16709)
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
2025-07-01 19:14:22 +02:00

69 lines
2.1 KiB
TypeScript

import { SecurityConfig } from '@n8n/config';
import { Command } from '@n8n/decorators';
import { Container } from '@n8n/di';
import { UserError } from 'n8n-workflow';
import z from 'zod';
import { RISK_CATEGORIES } from '@/security-audit/constants';
import type { Risk } from '@/security-audit/types';
import { BaseCommand } from './base-command';
const flagsSchema = z.object({
categories: z
.string()
.default(RISK_CATEGORIES.join(','))
.describe('Comma-separated list of categories to include in the audit'),
'days-abandoned-workflow': z
.number()
.int()
.default(Container.get(SecurityConfig).daysAbandonedWorkflow)
.describe('Days for a workflow to be considered abandoned if not executed'),
});
@Command({
name: 'audit',
description: 'Generate a security audit report for this n8n instance',
examples: ['', '--categories=database,credentials', '--days-abandoned-workflow=10'],
flagsSchema,
})
export class SecurityAudit extends BaseCommand<z.infer<typeof flagsSchema>> {
async run() {
const { flags: auditFlags } = this;
const categories =
auditFlags.categories?.split(',').filter((c): c is Risk.Category => c !== '') ??
RISK_CATEGORIES;
const invalidCategories = categories.filter((c) => !RISK_CATEGORIES.includes(c));
if (invalidCategories.length > 0) {
const message =
invalidCategories.length > 1
? `Invalid categories received: ${invalidCategories.join(', ')}`
: `Invalid category received: ${invalidCategories[0]}`;
const hint = `Valid categories are: ${RISK_CATEGORIES.join(', ')}`;
throw new UserError([message, hint].join('. '));
}
const { SecurityAuditService } = await import('@/security-audit/security-audit.service');
const result = await Container.get(SecurityAuditService).run(
categories,
auditFlags['days-abandoned-workflow'],
);
if (Array.isArray(result) && result.length === 0) {
this.logger.info('No security issues found');
} else {
process.stdout.write(JSON.stringify(result, null, 2));
}
}
async catch(error: Error) {
this.logger.error('Failed to generate security audit');
this.logger.error(error.message);
}
}