Inappropriate coding practices - Dart

Inappropriate coding practices - Dart

Need

Enforcement of proper encapsulation in coding practices

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in a Node.js application

Description

Non compliant code

        import 'package:shelf/shelf.dart' as shelf;

class User {
  public String name;
  public String password;
}

void main() {
  var app = shelf.Pipeline().addMiddleware(shelf.logRequests()).addHandler(_handler);
}

shelf.Response _handler(shelf.Request request) {
  User user = new User();
  user.name = "admin";
  user.password = "admin";
  // rest of the code
}
        
        

In the above code, the User class has two public fields: name and password. This is a clear violation of the encapsulation principle in object-oriented programming.

The encapsulation principle states that the internal state of an object should be hidden from the outside world. An object should be considered as a 'black box' that stores and manipulates data but does not expose the internal workings to the outside world.

In this scenario, by making the name and password fields public, we are exposing the internal state of the User object. Any class or function can modify these fields. This can lead to unforeseen side effects in other parts of the program if these fields are modified inappropriately.

Moreover, from a security standpoint, it is a bad practice to expose sensitive data like a user's password. If an attacker manages to get access to a User object, they can easily retrieve or change the user's password. This can lead to serious security breaches.

Therefore, it is important to make these fields private and provide public getter and setter methods to access and modify these fields, if necessary. This way, we can control how these fields are accessed and modified, and we can add additional logic in the getter and setter methods, like validation and encryption.

Steps

  • Change the access modifier of the fields in the User class from public to private. This can be done by prefixing the field names with an underscore.
  • Create getter and setter methods for the fields in the User class. This allows controlled access to the fields.
  • In the getter methods, simply return the value of the field.
  • In the setter methods, you can add any necessary logic to validate the input before setting the value of the field. For example, you could check if a password meets certain complexity requirements.

Compliant code

        import 'package:shelf/shelf.dart' as shelf;

class User {
  String _name;
  String _password;

  String get name => _name;
  set name(String name) => _name = name;

  String get password => _password;
  set password(String password) {
    // Add password complexity validation here if needed
    _password = password;
  }
}

void main() {
  var app = shelf.Pipeline().addMiddleware(shelf.logRequests()).addHandler(_handler);
}

shelf.Response _handler(shelf.Request request) {
  User user = new User();
  user.name = "admin";
  user.password = "admin";
  // rest of the code
}
        
        

The original code had a vulnerability due to inappropriate coding practices. The fields of the User class were defined as public, which does not respect the encapsulation principle of object-oriented programming. This could potentially allow unauthorized access and modification of these fields, leading to security issues.

The fixed code addresses this vulnerability by changing the access modifier of the fields in the User class from public to private. This is done by prefixing the field names with an underscore, which is the convention for private fields in Dart.

In addition, getter and setter methods are created for the fields in the User class. This allows controlled access to the fields. The getter methods simply return the value of the field, while the setter methods can contain any necessary logic to validate the input before setting the value of the field. For example, you could check if a password meets certain complexity requirements.

This way, the encapsulation principle is respected, and the security of the application is improved.

References