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 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 exists, 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.
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.
library(pkgaudit)
tarball <- system.file(
"extdata", "untrustedpkg", "untrustedpkg_0.1.0.tar.gz",
package = "pkgaudit"
)
result <- audit_tarball(tarball)
summary(result, path = FALSE)
#> --- pkgaudit Summary --------------------------------------------------------
#> Package: untrustedpkg v0.1.0 (source tarball)
#> SHA-256: 0c58ddcb365787ab7401c5eedaa4be7eb4ce6bea0a5ca290b6b7b1d8eb621d44
#> Scanned: 2026-08-27 01:16 UTC with pkgaudit v0.4.0, rules v0.4.0
#>
#> --- R Patterns --------------------------------------------------------------
#> phase rule n attck
#> at_build httr 1 T1041
#> at_build system 1 T1059.003 T1059.004
#> at_check download_file 1 T1105
#> at_check httr 1 T1041
#> at_check system 1 T1059.003 T1059.004
#> at_install_src httr 1 T1041
#> at_install_src system 1 T1059.003 T1059.004
#> at_load system 1 T1059.003 T1059.004
#> none download_file 1 T1105
#>
#> none: reported at no phase because nothing in the package was seen to call
#> it. Code under R/ is read this way by rule; a caller elsewhere, or a user,
#> can still reach it. See vignette("rules").
#>
#> --- Shell / Make Matches ----------------------------------------------------
#> phase rule n attck
#> at_build curl 1 T1041 T1105
#> at_check curl 1 T1041 T1105
#> 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
#> unexamined . DESCRIPTION 1
#>
#> --- Errors ------------------------------------------------------------------
#> No exceptions were raised.Phases overlap – building a package with vignettes, for example, also installs and loads it – and one occurrence is counted under every phase it runs in. The summary above reflects five findings, some counted under multiple phases.
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 to a directory for a scanner that can.
See Getting Started with pkgaudit for details.
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.