Sensitive information in source code - Credentials - Python

Sensitive information in source code - Credentials - Python

Need

Protection of sensitive information in source code

Context

  • Usage of Python 3 for writing Python code and running Python applications
  • Usage of Django for building web applications

Description

Non compliant code

        # settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

SECRET_KEY = 'mysecretkey'
API_KEY = 'myapikey'
        
        

The above code is a common configuration in Django's settings.py file. The DATABASES dictionary is used to configure the database parameters including the database name, user, password, host, and port.

The SECRET_KEY is a secret unique key for each Django project. It is used for cryptographic signing and should be kept safe.

The API_KEY is a key used for API access.

However, this code is vulnerable because it contains sensitive information
- the database credentials, secret key, and API key are all hard-coded into the source code.

This is a serious security issue because anyone who has access to this source code can see these credentials and potentially misuse them. This can lead to unauthorized access to the database, misuse of the API, and other potential security breaches.

To mitigate this vulnerability, sensitive information like this should be stored in environment variables or secure secret management systems, not in the source code.

Steps

  • Remove sensitive information like usernames, passwords, API keys, and secret keys from the source code.
  • Use environment variables to store sensitive information. This way, the sensitive data is not exposed in the code.
  • Use a secure method to load these environment variables into your application. For example, you can use the 'os' module in Python to load these variables.
  • For Django applications, you can use packages like 'python-decouple' to separate the parameters from the source code.
  • Never commit sensitive information to version control systems. If you have already done so, make sure to remove it from the history.
  • Consider using secret management systems or services for handling sensitive data in a more secure and organized manner.

Compliant code

        # settings.py
import os
from decouple import Config, Csv

config = Config()

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': config('DB_NAME'),
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASSWORD'),
        'HOST': config('DB_HOST'),
        'PORT': config('DB_PORT'),
    }
}

SECRET_KEY = config('SECRET_KEY')
API_KEY = config('API_KEY')
        
        

The above code has been modified to remove the sensitive information from the source code and instead, it is now being loaded from environment variables.

The os module in Python is used to load these variables. However, for Django applications, it is recommended to use packages like 'python-decouple' to separate the parameters from the source code.

In the code, config is an instance of the Config class from the decouple module. This instance is used to fetch the environment variables.

The config function is used to fetch the value of the environment variable. If the environment variable is not set, a ValueError will be raised.

For example, config('DB_NAME') fetches the value of the 'DB_NAME' environment variable.

This way, sensitive data like database credentials, secret keys, and API keys are not exposed in the code.

Remember to never commit sensitive information to version control systems. If you have already done so, make sure to remove it from the history.

Consider using secret management systems or services for handling sensitive data in a more secure and organized manner.

References