RedHatProductSecurity / cvss-v4-calculator

CVSS v4.0 calculator
https://redhatproductsecurity.github.io/cvss-v4-calculator/
BSD 2-Clause "Simplified" License
34 stars 25 forks source link

API endpoint #56

Open skontar opened 5 months ago

skontar commented 5 months ago

It would be a good idea to have another address which can be queried with a vector and just return a JSON with a result, maybe also copy of provided vector, something like: https://redhatproductsecurity.github.io/cvss-v4-calculator/api/#CVSS:4.0/AV:A/AC:H/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N)

{
    "vector": "CVSS:4.0/AV:A/AC:H/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
    "score": 2.3,
    "severity": "low",
}
pandatix commented 5 months ago

May I suggest another structure for the API call : /api/v1/compute?vector=<cvss_v4_vector_here> This enable versionning API (good practice) and is more HTML5/REST-full compliant so will enable better software integration.

skontar commented 5 months ago

Sure thing. This makes perfect sense.

nickleali commented 5 months ago

Appreciate you looking into this!

Would it be useful to have the nomenclature of the JSON match with the CVSS v4.0 schema for consistency? https://www.first.org/cvss/cvss-v4.0.json

{ "vectorString": "CVSS:4.0/AV:A/AC:H/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N", "baseScore": 2.3, "baseSeverity": "low", }

And potentially adapt the score and severity based on Threat or Environmental metrics?

n3rada commented 2 months ago

Hi @nickleali, if my PR #59 is accepted, It will certainly facilitate the implementation of an API. For example, it could be done with this kind of server.js express file:

const express = require('express');
const app = express();
const port = 3000;

const { CVSS40, Vector } = require('./cvss40');

app.get('/api/v1/compute', (req, res) => {
  const vectorString = req.query.vector;

  if (!vectorString) {
    return res.status(400).json({ error: 'Vector parameter is required' });
  }

  try {
    // Create a new Vector instance with the provided string
    const vector = new Vector(vectorString);

    // Pass the Vector instance to the CVSS40 constructor
    const cvssInstance = new CVSS40(vector);

    // Respond with the CVSS instance (including the computed score and severity)
    res.json({
      score: cvssInstance.score,
      severity: cvssInstance.severity,
      equivalentClasses: vector.equivalentClasses,
      raw: vector.raw,
    });
  } catch (error) {
    console.error('Error processing CVSS vector:', error);
    res.status(400).json({ error: 'Invalid CVSS vector', details: error.message });
  }
});

app.listen(port, () => {
  console.log(`CVSS API listening at http://localhost:${port}`);
});

Then, you can request:

http://localhost:3000/api/v1/compute?vector=CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:H/E:A

In order to retrieve the json:

{
   "score":9.2,
   "severity":"Critical",
   "equivalentClasses":"001100",
   "raw":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:H/E:A"
}

This is just an example, and the implementation needs to be discussed with the people in charge, as I don't know what they prefer for deploying the site. Of course, you'd have to add flow limitation, entry verification, etc.

nickleali commented 2 months ago

I'm certainly not someone who should be doing code review, but something like this would work great as an API to the calculator.

I will have to check about how this is deployed on the FIRST infrastructure for a hosted version.

n3rada commented 2 months ago

I hope someone who can will read it tho' 😊

skontar commented 2 months ago

@n3rada I am sorry I missed the PR. I will ask my colleague who is much better at Javascript to have a look.