Skip to content

Latest commit

 

History

History
140 lines (111 loc) · 5.3 KB

File metadata and controls

140 lines (111 loc) · 5.3 KB

pkgaudit

Project Status: Active R-CMD-check coverage osv-scanner

pkgaudit scans R packages for security-relevant files and code without executing anything it scans. It reports what code does and when it runs, so code that runs automatically on install or load is distinguishable from code that runs only when called.

A general-purpose scanner like Semgrep can read R – but it reads scripts, not packages. It does not look for R inside an \examples{} block, an \Sexpr{} macro, or a vignette. It does not know that .onLoad() runs when a user calls library() or that a configure script runs on R CMD check. pkgaudit extracts code wherever it sits, scans it for functions and commands that need human review, and reports the lifecycle phases in which each finding runs.

For why this matters, see R Package Security. For the rule set, see Rule Coverage.

Installation

remotes::install_github("tylerjssmith/pkgaudit")

Usage

A source package tarball can be scanned before it is installed. The example below scans untrustedpkg, a small package shipped with pkgaudit for demonstration. We see that, when untrustedpkg is installed from source, its R code will make an HTTP request (httr) and invoke a shell command (system). Meanwhile, a shell script may invoke curl. A human reviewer should inspect each of these findings before installing the package.

library(pkgaudit)

tarball <- system.file(
  "extdata", "untrustedpkg", "untrustedpkg_0.1.0.tar.gz",
  package = "pkgaudit"
)

result <- audit_tarball(tarball)

summary(result, phase = "at_install_src", path = FALSE)
#> --- pkgaudit Summary --------------------------------------------------------
#> Package:   untrustedpkg v0.1.0 (source tarball)
#> SHA-256:   0c58ddcb365787ab7401c5eedaa4be7eb4ce6bea0a5ca290b6b7b1d8eb621d44
#> Scanned:   2026-09-02 22:34 UTC with pkgaudit v0.4.0, rules v0.5.0
#> Phases:    at_install_src
#> 
#> --- R Patterns --------------------------------------------------------------
#> phase            rule     n   attck
#> at_install_src   httr     1   T1041
#> at_install_src   system   1   T1059.003 T1059.004
#> 
#> --- Shell / Make Matches ----------------------------------------------------
#> phase            rule     n   attck
#> at_install_src   curl     1   T1041 T1105
#> 
#> --- Coverage ----------------------------------------------------------------
#> status    top_level   type    files   lines
#> parsed    R/          R           2       6
#> parsed    man/        Rd          1      12
#> matched   .           shell       1       3
#> 
#> --- Errors ------------------------------------------------------------------
#> No exceptions were raised.

The supported phases are: at_autoconf, at_build, at_check, at_install_src, at_install_bin, at_load, at_attach, at_unload, and at_detach. A finding with no phase, such as a pattern inside a regular function in R/, is reported as none.

pkgaudit can integrate its scan with other tools. emit_sarif() renders its results as SARIF 2.1.0, which editors and code-scanning platforms read directly. export_unscanned() exports code written in languages pkgaudit cannot read, like C and Python, to a directory for a scanner that can.

A finding is not an accusation. Nearly all of the patterns and matches flagged by pkgaudit have legitimate uses in R packages. pkgaudit helps to identify what deserves reviewer attention, not what is malicious.

See Getting Started with pkgaudit for details.

Rule Database Integrity

pkgaudit detects security-relevant files and code using a SQLite database of rules shipped at inst/db/rules.db. rules_version() returns the current version of the database:

rules_version()

Current Version: 0.5.0

load_rules() verifies the database against its bundled .sha256 sidecar on every call and refuses to load a modified database. To check an installed copy against the value published here:

digest::digest(
  system.file("db", "rules.db", package = "pkgaudit"),
  algo = "sha256",
  file = TRUE
)

Expected SHA-256: c00175fa304b75711f108a600912f8ce95dc3ea71b75a7dd7460ade5aa3a9933

Security

pkgaudit’s own security model, and how to report a vulnerability, are in SECURITY.md. To propose or revise a rule, see CONTRIBUTING.md. How pkgaudit works internally, for a reader auditing the source, is in Internals.

Citation

citation("pkgaudit")