SSL peer certificate or SSH remote key was not OK / SSL certificate problem: unable to get local issuer certificate

Greetings. I am quite lost on how to solve this issue, so genuinely any pointers would be appreciated. For the last month, I have been struggling to pull data from some APIs. Here's an easy repex:

> fredr::fredr_series_observations("DFF")
Error in curl::curl_fetch_memory(url, handle = handle): SSL peer certificate or SSH remote key was not OK [api.stlouisfed.org]: SSL certificate problem: unable to get local issuer certificate
Request failed [ERROR]. Retrying in 1 seconds...
Error in curl::curl_fetch_memory(url, handle = handle): SSL peer certificate or SSH remote key was not OK [api.stlouisfed.org]: SSL certificate problem: unable to get local issuer certificate
Request failed [ERROR]. Retrying in 2.2 seconds...
Error in curl::curl_fetch_memory(url, handle = handle) : 
  SSL peer certificate or SSH remote key was not OK [api.stlouisfed.org]: SSL certificate problem: unable to get local issuer certificate

So far, the same error has also happened to quantmod's and Bloomberg's APIs, which is the reason I'm writing here instead of in other forums.

For context: I am using a MacBook Air M1, OS Sequoia 15.3.2 as a work laptop, but I suspect the issue is related to our firm's security software ZScaler -- strangely, however, my coworker does not have those issues.

Anyway, dealing with the firm's IT team, I have been forwarded a .crt CA file meant to be installed in the "certificate repository that the application [RStudio] uses". However, I have absolutely no idea on how to proceed with this, and nor does anybody else I've contacted.

Any help is appreciated, thanks in advance

Hi @gustavomenezes ,

so you can either set an environment variable at the beginning of your script

Sys.setenv(CURL_CA_BUNDLE = "/path/to/your/ca-bundle.crt")

or

edit the .Renviron file (normally located in your home path) adding this line

CURL_CA_BUNDLE=/path/to/your/ca-bundle.crt
1 Like

(post deleted by author)

Hello, just providing an update: the APIs that were broken are now working; however, another two APIs that I use are now broken on my end. The last one is not particularly relevant to my purposes, but the first one also appeared with a different error message (self-signed certificate in certificate chain):

> sidrar::get_sidra(api="/t/8888/n1/all/v/12606/p/all/c544/129314/d/v12606%205")
All others arguments are desconsidered when 'api' is informed
Error in curl::curl_fetch_memory(url, handle = handle) : 
  SSL peer certificate or SSH remote key was not OK [apisidra.ibge.gov.br]: SSL certificate problem: self-signed certificate in certificate chain
> rbcb::get_series(433)
Error in `map()`:
ℹ In index: 1.
ℹ With name: 433.
Caused by error in `curl::curl_fetch_memory()`:
! SSL peer certificate or SSH remote key was not OK [api.bcb.gov.br]: SSL certificate problem: unable to get local issuer certificate
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/purrr_error_indexed>
Error in `map()`:
ℹ In index: 1.
ℹ With name: 433.
Caused by error in `curl::curl_fetch_memory()`:
! SSL peer certificate or SSH remote key was not OK [api.bcb.gov.br]: SSL certificate problem: unable to get local issuer certificate
---
Backtrace:
     ▆
  1. ├─rbcb::get_series(433)
  2. │ ├─rbcb::rbcb_get(objs, start_date, end_date, last)
  3. │ └─rbcb:::rbcb_get.sgs(objs, start_date, end_date, last)
  4. │   └─purrr::map_dfr(...)
  5. │     └─purrr::map(.x, .f, ...)
  6. │       └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
  7. │         ├─purrr:::with_indexed_errors(...)
  8. │         │ └─base::withCallingHandlers(...)
  9. │         ├─purrr:::call_with_cleanup(...)
 10. │         └─rbcb (local) .f(.x[[i]], ...)
 11. │           └─rbcb:::http_download("get", url)
 12. │             └─rbcb:::http_getter(...)
 13. │               └─httr::GET(url = url, config = list(), handle = h, if (verbose) verbose())
 14. │                 └─httr:::request_perform(req, hu$handle$handle)
 15. │                   ├─httr:::request_fetch(req$output, req$url, handle)
 16. │                   └─httr:::request_fetch.write_memory(req$output, req$url, handle)
 17. │                     └─curl::curl_fetch_memory(url, handle = handle)
 18. └─curl:::raise_libcurl_error(...)
 19.   └─base::stop(e)
Run rlang::last_trace(drop = FALSE) to see 3 hidden frames.
> rlang::last_trace(drop = FALSE)
<error/purrr_error_indexed>
Error in `map()`:
ℹ In index: 1.
ℹ With name: 433.
Caused by error in `curl::curl_fetch_memory()`:
! SSL peer certificate or SSH remote key was not OK [api.bcb.gov.br]: SSL certificate problem: unable to get local issuer certificate
---
Backtrace:
     ▆
  1. ├─rbcb::get_series(433)
  2. │ ├─rbcb::rbcb_get(objs, start_date, end_date, last)
  3. │ └─rbcb:::rbcb_get.sgs(objs, start_date, end_date, last)
  4. │   └─purrr::map_dfr(...)
  5. │     └─purrr::map(.x, .f, ...)
  6. │       └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
  7. │         ├─purrr:::with_indexed_errors(...)
  8. │         │ └─base::withCallingHandlers(...)
  9. │         ├─purrr:::call_with_cleanup(...)
 10. │         └─rbcb (local) .f(.x[[i]], ...)
 11. │           └─rbcb:::http_download("get", url)
 12. │             └─rbcb:::http_getter(...)
 13. │               └─httr::GET(url = url, config = list(), handle = h, if (verbose) verbose())
 14. │                 └─httr:::request_perform(req, hu$handle$handle)
 15. │                   ├─httr:::request_fetch(req$output, req$url, handle)
 16. │                   └─httr:::request_fetch.write_memory(req$output, req$url, handle)
 17. │                     └─curl::curl_fetch_memory(url, handle = handle)
 18. ├─curl:::raise_libcurl_error(...)
 19. │ └─base::stop(e)
 20. └─purrr (local) `<fn>`(`<crl_r___>`)
 21.   └─cli::cli_abort(...)
 22.     └─rlang::abort(...)

There is no "easy" way to fix this other then making a bundle with all certificates that you need. Self signed means the API uses a certificate which was not created by a accepted authority and is mostly something companies use for their internal pages. It just lasts longer - you can make a self signed certificate expire after 10 years for example, instead of a few months which is commonly set for "proper" certificates. Also its free :smiley: .

So either reach out to your IT and ask them if they could make the bundle with all self signed and other certificates for you or depending on the script, call the environment including/excluding the bundle that you need.

The worst option is ignoring ssl verification. I post this just for completion without providing code since it is bad practice and insecure. Setting this option will ignore all certificates leaving your open to attacks from malicious sites - but your headaches will be gone.