forked from Vero-protocol/vero-guardian-dashboard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVulnerabilityWarning.tsx
More file actions
149 lines (136 loc) · 5.46 KB
/
Copy pathVulnerabilityWarning.tsx
File metadata and controls
149 lines (136 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
'use client';
import { AlertTriangle, ExternalLink, Info, ShieldAlert, type LucideIcon } from 'lucide-react';
import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import type { VulnerabilityFinding, VulnerabilitySeverity } from './types';
interface VulnerabilityWarningProps {
finding: VulnerabilityFinding;
}
const SEVERITY_STYLES: Record<
VulnerabilitySeverity,
{
article: string;
badge: string;
icon: LucideIcon;
}
> = {
critical: {
article:
'border-red-300 bg-red-50 shadow-red-900/10 dark:border-red-800 dark:bg-red-950/40',
badge:
'border-red-300 bg-red-100 text-red-800 dark:border-red-700 dark:bg-red-900/60 dark:text-red-200',
icon: ShieldAlert,
},
high: {
article:
'border-orange-300 bg-orange-50 dark:border-orange-800 dark:bg-orange-950/30',
badge:
'border-orange-300 bg-orange-100 text-orange-800 dark:border-orange-700 dark:bg-orange-900/60 dark:text-orange-200',
icon: AlertTriangle,
},
medium: {
article:
'border-amber-300 bg-amber-50 dark:border-amber-800 dark:bg-amber-950/30',
badge:
'border-amber-300 bg-amber-100 text-amber-800 dark:border-amber-700 dark:bg-amber-900/60 dark:text-amber-200',
icon: AlertTriangle,
},
low: {
article:
'border-sky-200 bg-sky-50 dark:border-sky-800 dark:bg-sky-950/30',
badge:
'border-sky-200 bg-sky-100 text-sky-800 dark:border-sky-700 dark:bg-sky-900/50 dark:text-sky-200',
icon: Info,
},
info: {
article:
'border-slate-200 bg-slate-50 dark:border-slate-700 dark:bg-slate-800/50',
badge:
'border-slate-200 bg-white text-slate-700 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300',
icon: Info,
},
unknown: {
article:
'border-slate-200 bg-slate-50 dark:border-slate-700 dark:bg-slate-800/50',
badge:
'border-slate-200 bg-white text-slate-700 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300',
icon: Info,
},
};
function getSafeReferenceUrl(value: string | undefined): string | undefined {
if (!value) {
return undefined;
}
try {
const url = new URL(value);
return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : undefined;
} catch {
return undefined;
}
}
export default function VulnerabilityWarning({ finding }: VulnerabilityWarningProps): ReactElement {
const { t } = useTranslation();
const severityStyle = SEVERITY_STYLES[finding.severity];
const SeverityIcon = severityStyle.icon;
const safeUrl = getSafeReferenceUrl(finding.url);
return (
<article
className={`rounded-xl border p-4 shadow-sm ${severityStyle.article}`}
data-testid={`vulnerability-warning-${finding.severity}`}
>
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div className="min-w-0">
<div className="flex flex-wrap items-center gap-2">
<SeverityIcon className="h-5 w-5 shrink-0 text-slate-700 dark:text-slate-200" aria-hidden="true" />
<h3 className="font-semibold text-slate-950 dark:text-white">{finding.title}</h3>
</div>
<p className="mt-1 font-mono text-xs text-slate-500 dark:text-slate-400">{finding.id}</p>
</div>
<span className={`inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-bold uppercase tracking-wide ${severityStyle.badge}`}>
{finding.severity}
</span>
</div>
{finding.message ? (
<p className="mt-3 text-sm leading-6 text-slate-700 dark:text-slate-300">{finding.message}</p>
) : null}
<dl className="mt-4 grid gap-3 text-sm">
{finding.packageName ? (
<div>
<dt className="text-xs font-semibold uppercase text-slate-500 dark:text-slate-400">{t('vulnerabilityWarning.package')}</dt>
<dd className="mt-1 font-mono text-xs text-slate-800 dark:text-slate-200">{finding.packageName}</dd>
</div>
) : null}
{finding.location ? (
<div>
<dt className="text-xs font-semibold uppercase text-slate-500 dark:text-slate-400">{t('vulnerabilityWarning.location')}</dt>
<dd className="mt-1 font-mono text-xs text-slate-800 dark:text-slate-200">{finding.location}</dd>
</div>
) : null}
{finding.recommendation ? (
<div>
<dt className="text-xs font-semibold uppercase text-slate-500 dark:text-slate-400">{t('vulnerabilityWarning.recommendation')}</dt>
<dd className="mt-1 text-slate-800 dark:text-slate-200">{finding.recommendation}</dd>
</div>
) : null}
{finding.source || safeUrl ? (
<div className="flex flex-wrap items-center gap-3">
{finding.source ? (
<span className="text-xs font-medium text-slate-500 dark:text-slate-400">{t('vulnerabilityWarning.source')}{finding.source}</span>
) : null}
{safeUrl ? (
<a
href={safeUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 rounded text-xs font-semibold text-indigo-700 hover:underline focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:text-indigo-300"
>
{t('vulnerabilityWarning.reference')}
<ExternalLink className="h-3 w-3" aria-hidden="true" />
</a>
) : null}
</div>
) : null}
</dl>
</article>
);
}