27 Security with vcr

Refer to the security chapter for more general guidance.

27.1 Keeping secrets safe

To keep your secrets safe, you need to use parameters of vcr::vcr_configure() that tell vcr either where secrets are (and what to put in their place), or what secrets are (and what to put in their place). It is best if you know how secrets are used in requests: e.g. is the API key passed as a header or part of the query string? Maybe you will need different strategies for the different secrets (e.g. an OAuth2.0 access token will be set as Authorization header but an OAuth2.0 refresh token might be in a query string).

In all cases, it is crucial to look at your cassettes before putting them on the public web, just to be sure you got the configuration right!

27.1.1 If the secret is in a request header

You can use filter_request_headers!

There are different ways to use it.

# Remove one header from the cassettes
  filter_request_headers = "Authorization"

# Remove two headers from the cassettes
  filter_request_headers = c("Authorization", "User-Agent")

# Replace one header with a given string
  filter_request_headers = list(Authorization = "<<<not-my-bearer-token>>>")

27.1.2 If the secret is in a response header

You can use filter_response_headers that works like filter_request_headers.

27.1.3 If the secret is somewhere else

In this case you need to tell vcr what the secret string is via filter_sensitive_data. Do not write the secret string directly in the configuration, that’d defeat the purpose of protecting it! Have the secret in an environment variable for instance and tell vcr to read it from there.

The configuration parameter filter_sensitive_data accepts a named list.

Each element in the list should be of the following format:

thing_to_replace_it_with = thing_to_replace

We replace all instances of thing_to_replace with thing_to_replace_it_with.

Before recording (writing to a cassette) we do the replacement and then when reading from the cassette we do the reverse replacement to get back to the real data.

  filter_sensitive_data = list("<<<my_api_key>>>" = Sys.getenv('API_KEY'))

You want to make the string that replaces your sensitive string something that won’t be easily found elsewhere in the response body/headers/etc.

27.2 API keys and tests run in varied contexts

  • For real requests a real API key is needed.
  • For requests using cassettes a fake API key is needed to fool your package. That is why in our demo of vcr we set a fake API key in a test setup file.

27.3 Other security

Let us know about any other security concerns! Surely there’s things we haven’t considered yet.