Data uniqueness not properly verified - Python

Data uniqueness not properly verified - Python

Need

Enforce proper data uniqueness verification

Context

  • Usage of Python 3 for general-purpose programming and scripting
  • Usage of Django for building web applications in Python

Description

Non compliant code

        from django.db import models

class User(models.Model):
    username = models.CharField(max_length=200)
    email = models.EmailField(max_length=200)
        
        

In the above code snippet, we have a Django model called User with fields username and email.

The vulnerability lies in the fact that there are no constraints set to ensure the uniqueness of username and email fields. This means that multiple users can register with the same username or email which should not be the case as these fields should be unique to each user.

An attacker could potentially exploit this vulnerability by registering multiple accounts with the same username or email. This could lead to various issues including impersonation, data inconsistency, and could also interfere with functionalities like password reset, where the application might not be able to determine the correct account to reset the password for, if there are multiple accounts with the same email.

Steps

  • Add unique=True attribute to the fields that need to be unique such as username and email.
  • Use Django's built-in form validation to check for uniqueness before saving the data.
  • Handle the IntegrityError exception that Django raises when trying to save non-unique data.
  • Consider using Django's get_or_create method to avoid creating duplicate entries.

Compliant code

        from django.db import models
from django.core.exceptions import ValidationError

class User(models.Model):
    username = models.CharField(max_length=200, unique=True)
    email = models.EmailField(max_length=200, unique=True)

    def clean(self):
        # Check for existing username or email
        if User.objects.filter(username=self.username).exists():
            raise ValidationError("Username already exists.")
        if User.objects.filter(email=self.email).exists():
            raise ValidationError("Email already exists.")

    def save(self, *args, **kwargs):
        self.clean()
        return super(User, self).save(*args, **kwargs)
        
        

The updated code now includes the unique=True attribute for both the username and email fields in the User model. This ensures that Django's ORM will enforce uniqueness at the database level.

In addition to this, we have overridden the clean method of the model. This method is called before data is saved to the database. In this method, we check if a user with the same username or email already exists in the database. If such a user exists, we raise a ValidationError.

Finally, we override the save method of the model. In this method, we call the clean method to perform our custom validation before calling the save method of the superclass to actually save the data to the database.

This way, we ensure that the uniqueness of the username and email is validated at two levels
- at the database level and at the application level. This provides a robust defense against attempts to create users with duplicate usernames or emails.

References