Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
**Vulnerability:** Raw `stop()` and `warning()` calls without `call. = FALSE` in `llcont.R` and `vuongtest.R` exposed execution stack/call details when raised.
**Learning:** While some instances of `stop()` inside `tryCatch()` were previously fixed to hide the call stack, other standalone exceptions and warnings still leaked call context. Security must be consistently applied across the entire codebase.
**Prevention:** Always set `call. = FALSE` when using `stop()` or `warning()` to enforce a secure-by-default boundary and prevent internal execution paths from being disclosed to the end user.
## 2024-08-15 - Missing Argument Validation Exposing Internal Context
**Vulnerability:** The top-level functions `vuongtest()` and `icci()` accepted user inputs (e.g. vectors for boolean or choice parameters) without validation, which bypassed initial code guards and resulted in deep internal R errors like "the condition has length > 1". This exposes internal execution stack frames and implementation details to the user.
**Learning:** In R codebases, it is critical to actively validate the types and lengths of arguments passed to exported functions immediately upon entry to prevent unexpected error behaviors down the call stack.
**Prevention:** Always strictly validate argument types, lengths, and valid choice sets right at the start of any exported function. Ensure failure conditions use `stop(msg, call. = FALSE)` to fail securely.
2 changes: 2 additions & 0 deletions R/icci.R
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#' @export
icci <- function(object1, object2, conf.level=.95, ll1=llcont, ll2=llcont) {

if(!is.numeric(conf.level) || length(conf.level) != 1 || is.na(conf.level) || conf.level <= 0 || conf.level >= 1) stop("conf.level must be a single numeric value between 0 and 1", call. = FALSE)

## check objects, issue warnings/errors, get classes/calls
obinfo <- check.obj(object1, object2)
callA <- obinfo$callA; classA <- obinfo$classA
Expand Down
3 changes: 3 additions & 0 deletions R/vuongtest.R
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
#' @export
vuongtest <- function(object1, object2, nested=FALSE, adj="none", ll1=llcont, ll2=llcont, score1=NULL, score2=NULL, vc1=vcov, vc2=vcov) {

if(!is.logical(nested) || length(nested) != 1 || is.na(nested)) stop("nested must be a single logical value", call. = FALSE)
if(!is.character(adj) || length(adj) != 1 || !(adj %in% c("none", "aic", "bic"))) stop("adj must be one of 'none', 'aic', or 'bic'", call. = FALSE)

## check objects, issue warnings/errors, get classes/calls
obinfo <- check.obj(object1, object2)
callA <- obinfo$callA; classA <- obinfo$classA
Expand Down
Loading