Skip to content

Change data models, to fix existing issues #206

@sbs2001

Description

@sbs2001

Vulnerability model diff

Old Vulnerability model

class Vulnerability(models.Model):
   cve_id = models.CharField(max_length=50, help_text='CVE ID', unique=True, null=True)
   summary = models.TextField(help_text='Summary of the vulnerability', blank=True)
   cvss = models.FloatField(max_length=100, help_text='CVSS Score', null=True)

New Vulnerability model

In the new Vulnerability model, cvss which is a severity indicator, is removed, the reason being, every data source rates the same vulnerability differently, hence we need some additional context when talking about severity. Hence all severity related fields are moved to VulnerabilityReference.

I also felt moving reference_ids here makes more sense. We would want a way to avoid entries duplicate entries in reference_id which I guess is possible, check https://stackoverflow.com/questions/49252135/how-to-save-arrayfield-as-set-in-django

class Vulnerability(models.Model):
   vuln_id = models.CharField(max_length=50, help_text='CVE ID', unique=True, null=True)
   reference_ids = pgfields.ArrayField(
       models.CharField(max_length=50,help_text='Reference ID, eg:DSA-4465-1'),default=list)

ImpactedPackage

Note: We would delete ResolvedPackage and rename ImpactedPackage to something else. Since their exact funtionality can be mimicked by a more efficient boolean field. This will also reduce the number of db queries

Old ImpactedPackage

class ImpactedPackage(models.Model):
   vulnerability = models.ForeignKey(Vulnerability, on_delete=models.CASCADE)
   package = models.ForeignKey(Package, on_delete=models.CASCADE)

   class Meta:
       unique_together = ('vulnerability', 'package')

New ImpactedPackage

Note: This won't be called ImpactedPackage, please suggest a good name.

The version_range will contain mathematical comparator symbols like '<,>,=' , (This will also support complex ranges like >1.0.0, <9.8.10 basically anything that dephell_range_specifier.RangeSpecifier supports) . This is very useful in cases where the data sources don't provide concrete versions. In the cases where concrete versions are provided we can always have version_range= '=' .

I haven't figured out how to solve #141, need help . Maybe adding Importer FK might help.

class ImpactedPackage(models.Model):
   vulnerability = models.ForeignKey(Vulnerability, on_delete=models.CASCADE)
   package = models.ForeignKey(Package, on_delete=models.CASCADE)
   version_range = models.CharField(max_length=30,default='=')
   is_vulnerable = models.BooleanField()

   class Meta:
       unique_together = ('vulnerability', 'package', 'version_range')

VulnerabilityReference

Old VulnerabilityReference

class VulnerabilityReference(models.Model):
   vulnerability = models.ForeignKey(
       Vulnerability, on_delete=models.CASCADE)
   source = models.CharField(
       max_length=50, help_text='Source(s) name eg:NVD', blank=True)
   reference_id = models.CharField(
       max_length=50, help_text='Reference ID, eg:DSA-4465-1', blank=True)
   url = models.URLField(
       max_length=1024, help_text='URL of Vulnerability data', blank=True)

   class Meta:
       unique_together = ('vulnerability', 'source', 'reference_id', 'url')
      

New VulnerabilityReference

Lots of changes here. We have here a FK of Importer, which makes logical sense since different data sources will say different things about the same vulnerability(hence the new unique_together)
Other changes include addtion of more severity indicators and using pgfields.ArrayField to store urls because we don't want to create a VulnerabilityReference for each url with other fields having same data.

Updated

class VulnerabilityReference(models.Model):
   vulnerability = models.ForeignKey(
       Vulnerability, on_delete=models.CASCADE,required=True)
   source = models.ForeignKey(
       Importer, on_delete=models.CASCADE, required=True)
   urls = pgfields.ArrayField(models.URLField(
       max_length=1024, help_text='URL of Vulnerability data'),default=list)
   summary = models.TextField(help_text='Summary of the vulnerability', blank=True)
   class Meta:
       unique_together = ('vulnerability', 'source')

class VulnerabilityScore(models.Model):
 vulnerability_reference = models.ForeignKey(VulnerabilityReference, on_delete=models.CASCADE, required=True)
 type = models.CharField(max_length=50, help_text='Vulnerability score type', blank=True))
 score = models.FloatField()
 severity_text = models.CharField()

Gets us closer to fix #18, #157, #140, #209 and allows us to collect data from any advisories which don't provide concrete versions(but provide version ranges)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions