From eed6e1f0e12243072728b0a104d563f527f17046 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Mon, 22 Jun 2026 03:41:52 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20Fix=20error?= =?UTF-8?q?=20handling=20info=20leakage=20in=20llcont?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change ensures that expected errors in R's `dnorm` and `dmvnorm` are securely caught using `try(..., silent=TRUE)` so they don't leak stack traces or internal state information. --- .jules/sentinel.md | 4 ++++ R/llcont.R | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 .jules/sentinel.md 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