Files
SVE/src/utils/sve.ts
T

137 lines
4.7 KiB
TypeScript

/** 模块:SVE 数据归一化与 CVSS 工具(后端 JSON 字段为原样存储,前端做防御性归一化) */
export interface ProductItem {
name: string
version: string
fixedVersion?: string
}
export interface ReferenceItem {
type: string
title?: string
url: string
}
export interface RelatedItem {
id: string
relation?: string
}
const asRecord = (raw: unknown): Record<string, unknown> => {
return raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : {}
}
/** SveProducts:兼容 {name,version,fixedVersion} 与 {productName,productVersion,productFixedVersion} 两种形态 */
export function normalizeProducts(raw: unknown): ProductItem[] {
if (!Array.isArray(raw)) return []
return raw
.map((entry) => {
const r = asRecord(entry)
return {
name: String(r.name ?? r.productName ?? r.Name ?? r.product_name ?? ''),
version: String(r.version ?? r.productVersion ?? r.Version ?? r.product_version ?? ''),
fixedVersion: r.fixedVersion != null ? String(r.fixedVersion) : undefined,
}
})
.filter((p) => p.name || p.version)
}
/** SveReferences:兼容 {type,title,url} 与 {referenceType,referenceTitle,referenceUrl} 两种形态 */
export function normalizeReferences(raw: unknown): ReferenceItem[] {
if (!Array.isArray(raw)) return []
return raw
.map((entry) => {
const r = asRecord(entry)
return {
type: String(r.type ?? r.referenceType ?? r.Type ?? 'other'),
title: r.title != null ? String(r.title) : undefined,
url: String(r.url ?? r.referenceUrl ?? r.Url ?? r.link ?? ''),
}
})
.filter((ref) => ref.url)
}
/** SveRelatedSves:兼容 [{id,relation}] 与 [{SveID,relation}] 与 [字符串] 三种形态 */
export function normalizeRelated(raw: unknown): RelatedItem[] {
if (!Array.isArray(raw)) return []
return raw
.map((entry) => {
if (typeof entry === 'string') return { id: entry }
const r = asRecord(entry)
return {
id: String(r.id ?? r.SveID ?? r.sveId ?? ''),
relation: r.relation != null ? String(r.relation) : undefined,
}
})
.filter((rel) => rel.id)
}
/** 解析 CVSS 向量字符串为指标字典,如 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N */
export function parseCvssVector(vector: string): Record<string, string> {
const result: Record<string, string> = {}
for (const part of vector.split('/')) {
const m = /^([A-Z]{1,2}):(.+)$/.exec(part.trim())
if (m) result[m[1]] = m[2]
}
return result
}
/** 指标缩写 → 完整名(用于详情页展示) */
export const CVSS_METRIC_LABELS: Record<string, { en: string; zh: string }> = {
AV: { en: 'Attack Vector', zh: '攻击向量' },
AC: { en: 'Attack Complexity', zh: '攻击复杂度' },
PR: { en: 'Privileges Required', zh: '所需权限' },
UI: { en: 'User Interaction', zh: '用户交互' },
S: { en: 'Scope', zh: '影响范围' },
C: { en: 'Confidentiality', zh: '机密性' },
I: { en: 'Integrity', zh: '完整性' },
A: { en: 'Availability', zh: '可用性' },
}
/** 指标值 → 显示文本 */
export const CVSS_METRIC_VALUE_LABELS: Record<string, Record<string, { en: string; zh: string }>> = {
AV: {
N: { en: 'Network', zh: '网络' },
A: { en: 'Adjacent', zh: '相邻网络' },
L: { en: 'Local', zh: '本地' },
P: { en: 'Physical', zh: '物理' },
},
AC: {
L: { en: 'Low', zh: '低' },
H: { en: 'High', zh: '高' },
},
PR: {
N: { en: 'None', zh: '无' },
L: { en: 'Low', zh: '低' },
H: { en: 'High', zh: '高' },
},
UI: {
N: { en: 'None', zh: '无' },
R: { en: 'Required', zh: '需要' },
},
S: {
U: { en: 'Unchanged', zh: '未变更' },
C: { en: 'Changed', zh: '已变更' },
},
C: { N: { en: 'None', zh: '无' }, L: { en: 'Low', zh: '低' }, H: { en: 'High', zh: '高' } },
I: { N: { en: 'None', zh: '无' }, L: { en: 'Low', zh: '低' }, H: { en: 'High', zh: '高' } },
A: { N: { en: 'None', zh: '无' }, L: { en: 'Low', zh: '低' }, H: { en: 'High', zh: '高' } },
}
/** 参考类型标签 */
export const REFERENCE_TYPE_LABELS: Record<string, { en: string; zh: string }> = {
vendor: { en: 'Vendor Advisory', zh: '厂商公告' },
tech_doc: { en: 'Technical Documentation', zh: '技术文档' },
sve_guide: { en: 'SVE Guidance', zh: 'SVE 指导文档' },
research: { en: 'Research Paper', zh: '研究论文' },
other: { en: 'Other', zh: '其他' },
}
/** 相关关系标签 */
export const RELATED_RELATION_LABELS: Record<string, { en: string; zh: string }> = {
same_product: { en: 'Same Product', zh: '同一产品' },
similar_vuln: { en: 'Similar Vulnerability', zh: '类似漏洞' },
same_vendor: { en: 'Same Vendor', zh: '同一厂商' },
other: { en: 'Other Relationship', zh: '其他关系' },
}