Scan R Packages for Vulnerabilities

Scan R package dependencies for known security vulnerabilities using the OSV database, with support for renv.lock, installed libraries, and user-supplied package versions.


vulnr - 0.1.0

branch main dev
R CMD check main-build dev-build
test coverage main-test-coverage dev-test-coverage
lints main-lints dev-lints
vulnerabilities main vulnerabilities dev vulnerabilities

Scan R project dependencies for known security vulnerabilities.

Installation

# from cran
install.packages("vulnr")

# install from github
devtools::install_github("Dschaykib/vulnr")

library(vulnr)

Usage of vulnr

By default, check() inspects renv.lock and installed libraries, then queries the OSV database. You can also provide package names and optional versions directly. Missing versions (NA or "") are treated as unversioned queries.

vulnr::check(data = c("dplyr", "httr"))

vulnr::check(data = data.frame(
  Package = c("dplyr", "httr"),
  Version = c("1.1.4", NA_character_)
))

Output

check() prints a detailed report and a summary when vulnerabilities are found. The report is a message() and the summary can be a warning() or an error() depending on the settings. By default, findings are grouped by package. The following is an illustrative example (the identifiers and versions are placeholders):

example 1.0.0
  Severity  Upstream       Score  Fix               Reference
  CRITICAL  CVE-2026-1234  (9.8)  fix >= 1.0.1       [1]
  HIGH      CVE-2026-5678  (7.5)  no fix available   [1]

References:
[1]
data
Found 2 vulnerabilities in 1 package
  CRITICAL 1
  HIGH     1
  MEDIUM   0
  LOW      0

The report means that two known vulnerabilities were found in the installed example package. Upstream is the vulnerability identifier returned by the OSV database. Score is the CVSS 3.1 base score on a scale from 0.0 to 10.0; Severity is derived from that score. In CVSS 3.1, scores of 0.0, 0.1–3.9, 4.0–6.9, 7.0–8.9, and 9.0–10.0 correspond to None, Low, Medium, High, and Critical respectively. See the FIRST CVSS v3.1 specification for the scoring model and severity ranges.

Fix shows the first package version known to contain a fix, when OSV provides one. Reference points to the input source listed at the bottom of the report; [1] means that this finding came from the first source (for example, the renv.lock file). If no vulnerabilities are found, check() prints No known vulnerabilities found.

By default, error_level = "LOW", so any Low, Medium, High, or Critical finding causes check() to stop with an error after printing the report. Set a higher threshold such as error_level = "HIGH" if only High and Critical findings should fail the check. Use return_cves = TRUE to receive the underlying vulnerability data table instead of the formatted report.

TODO explain csv result without error more

Open Topics

  • [x] create functions
  • [x] create tests
  • [x] tests with all renv versions to get packages
  • [x] get installed packages
  • [x] test when no version of package is available
  • [x] make nice print out
  • [x] check API rate limits -> no limits stated in the OSV docs
  • [x] add API error handling
  • [x] set warning and error level based on severity, like choose a minimum severity for error and warning
  • [ ] test other ecosystem than CRAN
  • [ ] include CVSS_V2, CVSS_V4, ubuntu see: https://ossf.github.io/osv-schema/#severity-field
  • [ ] check next_page_token from osv
  • [ ] tackle todo notes in code
  • [ ] fix workflows with correct R versions for dependencies or adjust dependencies

License

MIT

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("vulnr")

0.1.0 by Jakob Gepp, 11 hours ago


https://github.com/Dschaykib/vulnr


Report a bug at https://github.com/Dschaykib/vulnr/issues


Browse source code at https://github.com/cran/vulnr


Authors: Jakob Gepp [cre, aut, cph]


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports data.table, httr, jsonlite, stats, tools, utils

Suggests testthat


See at CRAN