refactor(backend): hoist severity Sets to utils/severity.ts (#795)

Replaces five inline new Set([...]) literals scattered across
routes/security.ts and routes/fleet.ts with two shared constants
(FINDING_SEVERITIES, POLICY_SEVERITIES) exported from
utils/severity.ts. Pure refactor: no error response or status code
changes.

Closes #749
This commit is contained in:
Anso
2026-04-27 00:05:12 -04:00
committed by GitHub
parent 4c4394b97e
commit 8460ae9ede
3 changed files with 23 additions and 12 deletions
+2 -2
View File
@@ -20,6 +20,7 @@ import { getLatestVersion } from '../utils/version-check';
import { isValidStackName } from '../utils/validation';
import { isDebugEnabled } from '../utils/debug';
import { getErrorMessage } from '../utils/errors';
import { POLICY_SEVERITIES } from '../utils/severity';
import { CloudBackupService } from '../services/CloudBackupService';
import { NotificationService } from '../services/NotificationService';
import { buildLocalConfigurationStatus, type ConfigurationStatus } from './dashboard';
@@ -47,7 +48,6 @@ const UPDATE_TIMEOUT_MSG = 'Node did not come back online within 5 minutes.';
const EARLY_FAIL_MS = 180 * 1000; // 3 minutes before declaring a probable pull failure
const MAX_SYNC_ROWS = 5000;
const VALID_SEVERITY = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']);
const CVE_ID_RE = /^(CVE-\d{4}-\d{4,}|GHSA-[\w-]{14,})$/;
const isIntFlag = (v: unknown): v is 0 | 1 => v === 0 || v === 1;
@@ -56,7 +56,7 @@ function validateScanPolicyRow(row: unknown): string | null {
if (!row || typeof row !== 'object') return 'row must be an object';
const r = row as Record<string, unknown>;
if (typeof r.name !== 'string' || r.name.length === 0 || r.name.length > 200) return 'name must be a non-empty string';
if (typeof r.max_severity !== 'string' || !VALID_SEVERITY.has(r.max_severity)) return 'max_severity must be CRITICAL, HIGH, MEDIUM, or LOW';
if (typeof r.max_severity !== 'string' || !POLICY_SEVERITIES.has(r.max_severity)) return 'max_severity must be CRITICAL, HIGH, MEDIUM, or LOW';
if (r.stack_pattern !== null && typeof r.stack_pattern !== 'string') return 'stack_pattern must be a string or null';
if (typeof r.stack_pattern === 'string' && r.stack_pattern.length > 200) return 'stack_pattern is too long';
if (typeof r.node_identity !== 'string') return 'node_identity must be a string';
+6 -10
View File
@@ -12,6 +12,7 @@ import { applySuppressions } from '../utils/suppression-filter';
import { generateSarif } from '../services/SarifExporter';
import { getErrorMessage } from '../utils/errors';
import { isDebugEnabled } from '../utils/debug';
import { FINDING_SEVERITIES, POLICY_SEVERITIES } from '../utils/severity';
const CVE_ID_RE = /^(CVE-\d{4}-\d{4,}|GHSA-[\w-]{14,})$/;
@@ -269,8 +270,7 @@ securityRouter.get(
const severity = typeof req.query.severity === 'string'
? (req.query.severity.toUpperCase() as 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'UNKNOWN')
: undefined;
const validSeverities = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'UNKNOWN']);
if (severity && !validSeverities.has(severity)) {
if (severity && !FINDING_SEVERITIES.has(severity)) {
res.status(400).json({ error: 'Invalid severity filter' }); return;
}
const limit = req.query.limit ? Number(req.query.limit) : undefined;
@@ -299,8 +299,7 @@ securityRouter.get(
const severity = typeof req.query.severity === 'string'
? (req.query.severity.toUpperCase() as 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'UNKNOWN')
: undefined;
const validSeverities = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'UNKNOWN']);
if (severity && !validSeverities.has(severity)) {
if (severity && !FINDING_SEVERITIES.has(severity)) {
res.status(400).json({ error: 'Invalid severity filter' }); return;
}
const limit = req.query.limit ? Number(req.query.limit) : undefined;
@@ -326,8 +325,7 @@ securityRouter.get(
const severity = typeof req.query.severity === 'string'
? (req.query.severity.toUpperCase() as 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'UNKNOWN')
: undefined;
const validSeverities = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'UNKNOWN']);
if (severity && !validSeverities.has(severity)) {
if (severity && !FINDING_SEVERITIES.has(severity)) {
res.status(400).json({ error: 'Invalid severity filter' }); return;
}
const limit = req.query.limit ? Number(req.query.limit) : undefined;
@@ -428,8 +426,7 @@ securityRouter.post('/policies', authMiddleware, (req: Request, res: Response):
if (!name || typeof name !== 'string' || !name.trim()) {
res.status(400).json({ error: 'Policy name is required' }); return;
}
const validSeverities = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']);
if (!validSeverities.has(max_severity)) {
if (!POLICY_SEVERITIES.has(max_severity)) {
res.status(400).json({ error: 'max_severity must be CRITICAL, HIGH, MEDIUM, or LOW' }); return;
}
try {
@@ -473,8 +470,7 @@ securityRouter.put('/policies/:id', authMiddleware, (req: Request, res: Response
}
if (body.stack_pattern !== undefined) updates.stack_pattern = body.stack_pattern ? String(body.stack_pattern) : null;
if (body.max_severity !== undefined) {
const validSeverities = new Set(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']);
if (!validSeverities.has(body.max_severity)) {
if (!POLICY_SEVERITIES.has(body.max_severity)) {
res.status(400).json({ error: 'max_severity must be CRITICAL, HIGH, MEDIUM, or LOW' }); return;
}
updates.max_severity = body.max_severity;
+15
View File
@@ -8,6 +8,21 @@ export const SEVERITY_ORDER: VulnSeverity[] = [
'CRITICAL',
];
export const FINDING_SEVERITIES: ReadonlySet<string> = new Set<VulnSeverity>([
'CRITICAL',
'HIGH',
'MEDIUM',
'LOW',
'UNKNOWN',
]);
export const POLICY_SEVERITIES: ReadonlySet<string> = new Set<VulnSeverity>([
'CRITICAL',
'HIGH',
'MEDIUM',
'LOW',
]);
export function severityRank(severity: VulnSeverity | null | undefined): number {
if (!severity) return -1;
return SEVERITY_ORDER.indexOf(severity);