-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add security assessment via {oysteR} #272
base: master
Are you sure you want to change the base?
Changes from all commits
735029e
b8950b2
1816f07
d8bb71f
ba48a9a
20ce000
4bb0510
be63283
1b1eebe
2625d0f
1a7e7da
c81c54a
0eeafc4
07478e7
e18db11
45429cd
ebbecca
e9d5e25
b49af45
5c57b12
cac9499
2037deb
82e9090
6b73d22
14e6a50
3f5f9b8
9efd972
94e9fa0
4c23d2c
19ae89a
297a17e
66d73d1
96a14c6
1ae59ef
cac8ce0
4c7a013
8e98a05
8f13cf1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ Type: Package | |
Title: Risk Metrics to Evaluating R Packages | ||
Description: Facilities for assessing R packages against a number of metrics to | ||
help quantify their robustness. | ||
Version: 0.2.2 | ||
Version: 0.2.2.9000 | ||
Authors@R: c( | ||
person("R Validation Hub", role = c("aut"), email = "[email protected]"), | ||
person("Doug", "Kelkhoff", role = c("aut"), email = "[email protected]"), | ||
|
@@ -14,6 +14,7 @@ Authors@R: c( | |
person("Eric", "Milliman", role = c("aut")), | ||
person("Juliane", "Manitz", role = c("aut")), | ||
person("Mark", "Padgham", role = c("ctb")), | ||
person("Andrew", "Borgman", role = c("aut")), | ||
person("PSI special interest group Application and Implementation of Methodologies in Statistics", role = c("cph"))) | ||
URL: https://pharmar.github.io/riskmetric/, https://github.com/pharmaR/riskmetric | ||
BugReports: https://github.com/pharmaR/riskmetric/issues | ||
|
@@ -44,7 +45,8 @@ Suggests: | |
dplyr, | ||
testthat, | ||
webmockr, | ||
jsonlite | ||
jsonlite, | ||
oysteR (>= 0.1.0) | ||
RoxygenNote: 7.2.3 | ||
VignetteBuilder: knitr | ||
Config/testthat/edition: 3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#' Assess a package for known security vulnerabilities in the OSS Index | ||
#' | ||
#' @param x a \code{pkg_ref} package reference object | ||
#' @param ... additional arguments passed on to S3 methods, rarely used | ||
#' @return a \code{pkg_metric} containing Assess for any known security vulnerabilities in the OSS Index via oysteR | ||
#' @seealso \code{\link{metric_score.pkg_metric_security}} | ||
#' | ||
#' @importFrom utils install.packages menu | ||
#' @export | ||
assess_security <- function(x, ...) { | ||
|
||
# checks whether a compatible version of oysteR is installed. prompts user to | ||
# install or upgrade if needed when running interactively. an error is thrown | ||
# in the event a valid oysteR package is not installed. | ||
cf <- deparse(match.call()[[1]]) | ||
validate_suggests_install(pkg_name = "oysteR", calling_fn = cf) | ||
|
||
UseMethod("assess_security") | ||
} | ||
|
||
attributes(assess_security)$column_name <- "security" | ||
attributes(assess_security)$label <- | ||
"number of vulnerabilities detected in OSS Index" | ||
|
||
# set as a "Suggests" package to be excluded from all_assessments if the package | ||
# is not installed | ||
attributes(assess_security)$suggests <- !requireNamespace("oysteR", quietly = TRUE) | ||
attributes(assess_security)$suggests_pkg <- "oysteR" | ||
|
||
|
||
#' @export | ||
assess_security.default <- function(x, ...) { | ||
pkg_metric_eval(class = "pkg_metric_security", { | ||
x$security | ||
}) | ||
} | ||
|
||
|
||
#' Score a package for known security vulnerabilities in the OSS Index | ||
#' | ||
#' Coerce the count of reported vulnerabilities to a binary indicator. | ||
#' | ||
#' @eval roxygen_score_family("security", dontrun = TRUE) | ||
#' @return \code{NA} if no vulnerabilities are found, otherwise \code{0} | ||
#' | ||
#' @export | ||
metric_score.pkg_metric_security <- function(x, ...) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we can capture the vulnerability overivew then we could set metric to |
||
if (x < 1) return(NA) | ||
else return(0) | ||
} | ||
attributes(metric_score.pkg_metric_security)$label <- | ||
"A binary indicator of whether a package has OSS Index listed vulnerabilities." | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
riskmetric.options <- list( | ||
gitlab_api_host = "https://gitlab.com/api/v4", | ||
github_api_host = "https://api.github.com" | ||
github_api_host = "https://api.github.com", | ||
skip_oysteR_install = FALSE | ||
) |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think for the ref_cache we should capture the oysteR output, if ony the tibble to start, but the entire message would be best (especially the overview).
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#' Cache OSS Index results | ||
#' | ||
#' @inheritParams pkg_ref_cache | ||
#' @family package reference cache | ||
#' @return a \code{pkg_ref} object | ||
#' @keywords internal | ||
#' @noRd | ||
pkg_ref_cache.security <- function(x, ...) { | ||
validate_suggests_install( | ||
pkg_name = "oysteR", | ||
calling_fn = deparse(match.call()[[1]]) | ||
) | ||
UseMethod("pkg_ref_cache.security") | ||
} | ||
|
||
#' Check OSS Index lists any vulnerabilities for the package | ||
#' | ||
#' @inheritParams pkg_ref_cache | ||
#' @family package reference cache | ||
#' @return a \code{pkg_ref} object | ||
#' @keywords internal | ||
#' @noRd | ||
pkg_ref_cache.security.default <- function(x, ...) { | ||
scan_results <- oysteR::audit( | ||
pkg = x$name, | ||
version = as.character(x$version), | ||
type = "cran", | ||
verbose = FALSE | ||
) | ||
|
||
return(sum(scan_results[["no_of_vulnerabilities"]])) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#' Helper function to prompt to install a package if it is not present | ||
#' | ||
#' @keywords internal | ||
#' | ||
validate_suggests_install <- function(pkg_name, calling_fn) { | ||
# check if package is installed | ||
if (!requireNamespace(pkg_name, quietly = TRUE)) { | ||
# if not, prompt for install | ||
suggests_install_helper(pkg_name, calling_fn) | ||
} | ||
} | ||
|
||
#' Helper function to guide user through install of a package | ||
#' | ||
#' @importFrom stats setNames | ||
#' @keywords internal | ||
#' | ||
suggests_install_helper <- function(pkg_name, calling_fn) { | ||
op_nm <- sprintf("riskmetric.skip_%s_install", pkg_name) | ||
if (interactive() & !getOption(op_nm)) { | ||
inst_yn <- utils::menu( | ||
choices = c("Yes", "No"), | ||
title = sprintf( | ||
"Running %s requires installation of the of the %s package. | ||
Would you like to install this now?", | ||
calling_fn, pkg_name | ||
) | ||
) | ||
|
||
if (inst_yn == "1") { | ||
utils::install.packages(pkg_name) | ||
} else { | ||
# if user skipped once, don't prompt again until session restarts | ||
if (inst_yn == "2") do.call(options, as.list(setNames(TRUE, op_nm))) | ||
stop(sprintf( | ||
"%s not run. Please install the %s package if you wish to proceed.", | ||
calling_fn, pkg_name | ||
)) | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the assessment should be the tibble or possibly the list of vulnerabilities found. and then metric can be binary or presence/absence of vulnerabilities.