defender

Travis build status Coverage status Lifecycle Status

The goal of defender is to do static code analysis on other R packages to check for potential security risks and best practices. It provides checks on multiple levels:


  1. x
    static code analysis without installing the package


  2. more thorough but potentially dangerous checks with installation / in Docker container

The checks do not tell you whether something is harmful but rather they flag code that you should double-check before running / loading the package.

Installation

You can install defender from github with:

# install.packages("devtools")
devtools::install_github("ropenscilabs/defender")

Example

System calls in R scripts

You can check for system calls in any directory locally available:

defender::summarize_system_calls("../testevil")
#>                path line_number                     call
#> 1   inst/root_sys.R           1            system2("ls")
#> 2   inst/root_sys.R           4             system("ls")
#> 3      R/exported.R           7            system2("ls")
#> 4      R/internal.R           4             system("ls")
#> 5      R/internal.R           8         system("ls -la")
#> 6      R/processx.R           3      processx::run("ls")
#> 7           R/sys.R           8 sys::exec_internal("ls")
#> 8 R/system_hidden.R           2            system2("lm")
#>        function_name
#> 1            system2
#> 2             system
#> 3            system2
#> 4             system
#> 5             system
#> 6      processx::run
#> 7 sys::exec_internal
#> 8            system2

You can also include additional elements to flag as dangerous:

sc <- defender::system_calls("poll")
defender::summarize_system_calls("../testevil", calls_to_flag = sc)
#>                path line_number                     call
#> 1   inst/root_sys.R           1            system2("ls")
#> 2   inst/root_sys.R           4             system("ls")
#> 3      R/exported.R           7            system2("ls")
#> 4      R/internal.R           4             system("ls")
#> 5      R/internal.R           8         system("ls -la")
#> 6      R/processx.R           9               poll("ls")
#> 7      R/processx.R           3      processx::run("ls")
#> 8           R/sys.R           8 sys::exec_internal("ls")
#> 9 R/system_hidden.R           2            system2("lm")
#>        function_name
#> 1            system2
#> 2             system
#> 3            system2
#> 4             system
#> 5             system
#> 6               poll
#> 7      processx::run
#> 8 sys::exec_internal
#> 9            system2

Collaborators

  • Ildi Czeller @czeildi
  • Karthik Ram @karthik
  • Bob Rudis @hrbrmstr
  • Kara Woo @karawoo