Inappropriate coding practices - Python

Inappropriate coding practices - Python

Need

Enforce proper encapsulation in coding practices

Context

  • Usage of Python 3 for writing and executing Python code

Description

Non compliant code

        class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        
        

In the code snippet above, we have a User class with two public fields: username and password. This is considered a vulnerability because it does not respect the principle of encapsulation.

Encapsulation is one of the fundamental concepts in object-oriented programming (OOP). It refers to the bundling of data with the methods that operate on that data. Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties' direct access to them.

However, in the above code, the username and password fields are public, meaning they can be accessed and modified directly from outside the class. This can lead to inappropriate or unexpected changes to these fields, leading to potential security risks or bugs in the software.

For instance, an attacker could change the password field of a User object without going through a proper password change procedure (which might involve checking the old password, enforcing password strength rules, etc.).

Therefore, it is generally a good practice to make fields private (or protected) and provide public getter and setter methods to access and modify them. This way, you can control and validate how and when these fields are accessed or changed.

Steps

  • Change the access modifier of the fields to private. This can be done by prefixing the field names with double underscores.
  • Create getter and setter methods for each field. The getter method will return the value of the field, and the setter method will set the value of the field.
  • In the setter methods, you can add validation logic to ensure that only valid data is set to the fields.
  • Replace all direct accesses to the fields with calls to the getter and setter methods.

Compliant code

        class User:
    def __init__(self, username, password):
        self.__username = username
        self.__password = password

    # Getter method for username
    @property
    def username(self):
        return self.__username

    # Setter method for username
    @username.setter
    def username(self, username):
        self.__username = username

    # Getter method for password
    @property
    def password(self):
        return self.__password

    # Setter method for password
    @password.setter
    def password(self, password):
        self.__password = password
        
        

The above code fixes the vulnerability by making the username and password fields private. This is done by prefixing the field names with double underscores. This ensures that these fields cannot be accessed directly from outside the class, thus respecting the principle of encapsulation.

Getter and setter methods are created for each field. The getter method, decorated with @property, returns the value of the field. The setter method, decorated with @field_name.setter, sets the value of the field. These methods allow controlled access to the private fields.

In the setter methods, you can add validation logic to ensure that only valid data is set to the fields. For example, you could check that the username is a non-empty string and that the password meets certain complexity requirements.

Finally, all direct accesses to the fields are replaced with calls to the getter and setter methods. This ensures that the fields are always accessed in a controlled manner, further enhancing the security of the code.

References