|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CVSS { |
|
constructor(id, options = {}) { |
|
this.options = options; |
|
this.containerId = id; |
|
this.container = document.getElementById(id); |
|
this.baseMetrics = this.getBaseMetrics(); |
|
this.metricElements = {}; |
|
this.setupUI(); |
|
} |
|
|
|
getBaseMetrics() { |
|
return { |
|
AV: { label: 'Attack Vector', values: { N: 'Network', A: 'Adjacent', L: 'Local', P: 'Physical' }}, |
|
AC: { label: 'Attack Complexity', values: { L: 'Low', H: 'High' }}, |
|
PR: { label: 'Privileges Required', values: { N: 'None', L: 'Low', H: 'High' }}, |
|
UI: { label: 'User Interaction', values: { N: 'None', R: 'Required' }}, |
|
S: { label: 'Scope', values: { C: 'Changed', U: 'Unchanged' }}, |
|
C: { label: 'Confidentiality', values: { H: 'High', L: 'Low', N: 'None' }}, |
|
I: { label: 'Integrity', values: { H: 'High', L: 'Low', N: 'None' }}, |
|
A: { label: 'Availability', values: { H: 'High', L: 'Low', N: 'None' }} |
|
}; |
|
} |
|
|
|
setupUI() { |
|
if (!this.container) return; |
|
|
|
const form = document.createElement('form'); |
|
form.className = 'cvss-form'; |
|
|
|
for (let metric in this.baseMetrics) { |
|
const metricData = this.baseMetrics[metric]; |
|
const dl = document.createElement('dl'); |
|
dl.className = metric; |
|
|
|
const dt = document.createElement('dt'); |
|
dt.textContent = metricData.label; |
|
dl.appendChild(dt); |
|
|
|
for (let value in metricData.values) { |
|
const dd = document.createElement('dd'); |
|
dl.appendChild(dd); |
|
|
|
const input = document.createElement('input'); |
|
input.type = 'radio'; |
|
input.name = metric; |
|
input.value = value; |
|
input.id = `${this.containerId}-${metric}-${value}`; |
|
input.className = `${metric}-${value}`; |
|
input.addEventListener('change', () => this.updateMetric(metric, value)); |
|
|
|
this.metricElements[`${metric}-${value}`] = input; |
|
dd.appendChild(input); |
|
|
|
const label = document.createElement('label'); |
|
label.setAttribute('for', input.id); |
|
label.textContent = metricData.values[value]; |
|
dd.appendChild(label); |
|
} |
|
form.appendChild(dl); |
|
} |
|
|
|
this.container.appendChild(form); |
|
this.form = form; |
|
} |
|
|
|
updateMetric(metric, value) { |
|
|
|
console.log(`Metric ${metric} changed to ${value}`); |
|
if (this.options.onchange) this.options.onchange(); |
|
} |
|
|
|
set(vector) { |
|
const metrics = vector.split('/'); |
|
metrics.forEach(pair => { |
|
const [metric, value] = pair.split(':'); |
|
if (this.metricElements[`${metric}-${value}`]) { |
|
this.metricElements[`${metric}-${value}`].checked = true; |
|
} |
|
}); |
|
} |
|
|
|
get() { |
|
const result = { score: 0, vector: [] }; |
|
for (let metric in this.baseMetrics) { |
|
const checkedInput = this.form.querySelector(`input[name=${metric}]:checked`); |
|
if (checkedInput) { |
|
result.vector.push(`${metric}:${checkedInput.value}`); |
|
} |
|
} |
|
result.vector = result.vector.join('/'); |
|
|
|
result.score = this.calculateScore(result.vector); |
|
return result; |
|
} |
|
|
|
calculateScore(vector) { |
|
|
|
return Math.random() * 10; |
|
} |
|
} |
|
|