Because it is easy to extract strings from an application source code or binary, secrets should not be hard-coded. This is particularly true for
applications that are distributed or that are open-source.
In the past, it has led to the following vulnerabilities:
Secrets should be stored outside of the source code in a configuration file or a management service for secrets.
This rule detects variables/fields having a name matching a list of words (secret, token, credential, auth, api[_.-]?key) being assigned a
pseudorandom hard-coded value. The pseudorandomness of the hard-coded value is based on its entropy and the probability to be human-readable. The
randomness sensibility can be adjusted if needed. Lower values will detect less random values, raising potentially more false positives.
Ask Yourself Whether
- The secret allows access to a sensitive component like a database, a file storage, an API, or a service.
- The secret is used in a production environment.
- Application re-distribution is required before updating the secret.
There would be a risk if you answered yes to any of those questions.
Recommended Secure Coding Practices
- Store the secret in a configuration file that is not pushed to the code repository.
- Use your cloud provider’s service for managing secrets.
- If a secret has been disclosed through the source code: revoke it and create a new one.
Sensitive Code Example
private val MY_SECRET = "47828a8dd77ee1eb9dde2d5e93cb221ce8c32b37"
fun main() {
MyClass.callMyService(MY_SECRET)
}
Compliant Solution
Using AWS Secrets Manager:
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
fun main() {
SecretsManagerClient secretsClient = ...
MyClass.doSomething(secretsClient, "MY_SERVICE_SECRET")
}
fun doSomething(secretsClient: SecretsManagerClient, secretName: String) {
val valueRequest = GetSecretValueRequest.builder()
.secretId(secretName)
.build()
val valueResponse = secretsClient.getSecretValue(valueRequest)
val secret = valueResponse.secretString()
// do something with the secret
MyClass.callMyService(secret)
}
Using Azure Key Vault Secret:
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
fun main() {
val keyVaultName = System.getenv("KEY_VAULT_NAME")
val keyVaultUri = "https://$keyVaultName.vault.azure.net"
val secretClient = SecretClientBuilder()
.vaultUrl(keyVaultUri)
.credential(DefaultAzureCredentialBuilder().build())
.buildClient()
MyClass.doSomething(secretClient, "MY_SERVICE_SECRET")
}
fun doSomething(secretClient: SecretClent, secretName: String) {
val retrievedSecret = secretClient.getSecret(secretName)
val secret = retrievedSecret.getValue()
// do something with the secret
MyClass.callMyService(secret)
}
See