diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..534b988 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-23 - Secure Error Handling in R Packages +**Vulnerability:** Uncaught or non-silent errors in R packages can bubble up and leak internal stack traces or internal state information to users or logs, which is a security risk. In `R/llcont.R`, log-likelihood calculations using `dnorm` and `dmvnorm` could fail, but only one case was wrapped in `try()` (without `silent=TRUE`) and the others had no `try()` wrapper despite expecting to catch errors using `inherits(tmpll.x, "try-error")`. +**Learning:** `try()` calls in R should use `silent=TRUE` when the goal is to securely catch exceptions and return an expected default (like `NA`), instead of exposing the error details to the caller or console. +**Prevention:** Always verify that code that expects `try-error` actually wraps its execution in `try(..., silent=TRUE)`. diff --git a/R/llcont.R b/R/llcont.R index 5896c33..23e45e6 100644 --- a/R/llcont.R +++ b/R/llcont.R @@ -424,9 +424,9 @@ llcont.lavaan <- function(x, ...){ } if(length(x.idx) == 1){ - tmpll.x <- dnorm(x@Data@X[[g]][,x.idx], Mu.X, sqrt(Sigma.X), log=TRUE) + tmpll.x <- try(dnorm(x@Data@X[[g]][,x.idx], Mu.X, sqrt(Sigma.X), log=TRUE), silent=TRUE) } else { - tmpll.x <- dmvnorm(x@Data@X[[g]][,x.idx], Mu.X, Sigma.X, log=TRUE) + tmpll.x <- try(dmvnorm(x@Data@X[[g]][,x.idx], Mu.X, Sigma.X, log=TRUE), silent=TRUE) } if(inherits(tmpll.x, "try-error")) tmpll.x <- NA llvec[grpind] <- llvec[grpind] - tmpll.x @@ -466,9 +466,9 @@ llcont.lavaan <- function(x, ...){ Sigma.X <- Sigma.hat[x.idx, x.idx, drop=FALSE] if(length(x.idx) == 1){ - tmpll.x <- dnorm(X[,x.dat.idx], Mu.X, sqrt(Sigma.X), log=TRUE) + tmpll.x <- try(dnorm(X[,x.dat.idx], Mu.X, sqrt(Sigma.X), log=TRUE), silent=TRUE) } else { - tmpll.x <- try(dmvnorm(X[,x.dat.idx], Mu.X, Sigma.X, log=TRUE)) + tmpll.x <- try(dmvnorm(X[,x.dat.idx], Mu.X, Sigma.X, log=TRUE), silent=TRUE) } if(inherits(tmpll.x, "try-error")) tmpll.x <- NA tmpll[case.idx] <- tmpll[case.idx] - tmpll.x