Protection of sensitive information in source code
package utils
object Config {
val dbUsername = "admin"
val dbPassword = "password123"
val awsSecretKey = "test"
val adminEmail = "admin@example.com"
val serverIp = "192.168.1.1"
}
This Scala code snippet is an example of a vulnerable practice in handling sensitive information. The
Config
object is storing sensitive information such as a database username and password, an AWS secret key, an admin email, and a server IP address.
The problem with this approach is that the sensitive data is stored in plain text directly in the source code. This is a bad practice because:
1. Exposure of sensitive data: If the source code is ever exposed or shared, the sensitive data will be exposed as well. This could lead to unauthorized access to the resources these credentials protect.
2. Lack of encryption: The sensitive data is not encrypted, making it easy for anyone who has access to the source code to read and misuse the data.
3. Version control issues: Storing sensitive data in the source code means that the data will be included in the version control system (like Git). This means that even if the sensitive data is removed from the latest version of the code, it will still exist in the version control history.
4. Inflexibility: Hard-coding credentials into the source code makes it difficult to change them without changing the code and redeploying the application. It also makes it impossible to use different credentials for different environments (e.g. development, testing, production).
To fix this vulnerability, sensitive data should be removed from the source code and instead be securely managed using environment variables, encrypted configuration files, or dedicated secret management systems.
package utils
import com.typesafe.config.ConfigFactory
object Config {
private val config = ConfigFactory.load()
val dbUsername: String = config.getString("db.username")
val dbPassword: String = config.getString("db.password")
val awsSecretKey: String = config.getString("aws.secretKey")
val adminEmail: String = config.getString("admin.email")
val serverIp: String = config.getString("server.ip")
}
The updated code no longer contains sensitive information directly in the source code. Instead, it uses the Typesafe Config library to load these values from a configuration file. This configuration file should be stored securely and not included in the source code repository.
The
ConfigFactory.load()
method loads configuration in the following order:
1. System properties
2. Application properties: application.conf, application.json, application.properties
3. Default configuration: reference.conf
This allows you to override configuration values with system properties, which can be useful for setting sensitive data like passwords or secret keys in a production environment.
Here is an example of what the
application.conf
file might look like:
db {
username = "admin"
password = "password123"
}
aws {
secretKey = "test"
}
admin {
email = "admin@example.com"
}
server {
ip = "192.168.1.1"
}