Detect Dangerous Function Calls in an R Expression
Source:R/find_dangerous_calls.R
find_dangerous_calls.Rd
Recursively inspects an R expression and identifies any calls to functions listed in a forbidden list. This is useful for validating code generated by large language models (LLMs) or user input before evaluating it.
Arguments
- expr
An R expression or language object, typically returned by
base::parse()
.- additional_forbidden
A character vector of function names to flag as disallowed. These are combined with the vector of function names from
default_dangerous_calls()
- block_namespace_access
A logical indicating whether to block namespace access operators (
::
and:::
) in the expression.
Value
A character vector of disallowed function names that were found in the expression.
If none were found, returns character(0)
.
Details
This function traverses the expression tree recursively and checks whether any of the
function calls match names in the forbidden
list. It does not evaluate the expression,
and it does not inspect calls constructed dynamically (e.g., via get()
or match.fun()
).
Only syntactic references to function names are detected.
This function is useful in contexts where LLMs or other tools generate R code dynamically, and you want to enforce a safety layer before evaluation.
Examples
# Basic example with raw code
find_dangerous_calls(parse(text = "system('ls')"))
#> [1] "system"
# Multiple disallowed calls
expr <- parse(text = "unlink('file'); system2('echo', 'hi')")
find_dangerous_calls(expr)
#> [1] "unlink" "system2"
# Using base:: syntax
find_dangerous_calls(parse(text = "base::system2('echo', 'hi')" ))
#> [1] "system2" "::"
# Using namespace access with `::` or `:::`
find_dangerous_calls(parse(text = 'purr::map(1:3, ~ base::system("echo hi"))'))
#> [1] "::" "system"
# Safe code
find_dangerous_calls(parse(text = "mean(c(1, 2, 3))"))
#> character(0)