OHDSI / DatabaseConnector

An R package for connecting to databases using JDBC.
http://ohdsi.github.io/DatabaseConnector/
54 stars 80 forks source link

Connection details store password unencrypted #126

Closed schuemie closed 3 years ago

schuemie commented 4 years ago

The current implementation of createConnectionDetails() stores any password the user might provide without encryption in R's memory. If users save their session workspace, it may even get saved to file unencrypted.

A solution might be to delay evaluation of the connection detail arguments. Here's an example:

# Add a test password:
keyring::key_set_with_value("secret", password = "helloWorld")

# Function for creating connection details:
createCd <- function(password) {
  return(list(password = match.call()[[2]])) 
}

# Call function using keyring:
cd <- createCd(password = keyring::key_get("secret"))               

# Arguments are not yet evaluated:
cd
# $password
# keyring::key_get("secret")

# Can be evaluated when needed:
eval(cd$password)
# [1] "helloWorld"

Adding @ablack3 , @gowthamrao .

ablack3 commented 4 years ago

I agree that storing a user's password, even temporarily in memory, can be problematic. We should probably just assume that all passwords are highly sensitive. The contents of a connectionDetails object is sometimes printed out to log files like the ones created by ParallelLogger and RStudio Server.

Here is an rlang/tidyeval version.

# Add a test password:
keyring::key_set_with_value("secret", password = "helloWorld")

# Function for creating connection details:
createCd <- function(password) {
  passwordExpression <- rlang::enquo(password)
  list(password = function() rlang::eval_tidy(passwordExpression))
}

# Call function using keyring:
cd <- createCd(password = keyring::key_get("secret"))               

# The list does not contain the password so it won't inadvertently get printed or saved as text
print(cd)
#> $password
#> function() rlang::eval_tidy(passwordExpression)
#> <environment: 0x0000000014f22830>

# Calling the password function will evaluate the expression and return the password
cd$password()
#> [1] "helloWorld"