Sensitive information in source code - Credentials
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.