diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 00000000..b16984e6 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1 @@ +## 2026-07-22 - Prevent Leaking Sensitive Info in Error Responses\n**Vulnerability:** Redacted error messages used `%w` to wrap errors which still leaked sensitive info through the underlying error object.\n**Learning:** When applying string redactors (like `redaction.ErrorMessage`), the original error shouldn't be wrapped. Instead, it must be stringified with `%s` before redacting so that only the safe redacted text persists.\n**Prevention:** Avoid `%w` when formatting errors that contain secrets prior to redacting. diff --git a/internal/cli/trust.go b/internal/cli/trust.go index 8b025ab6..2d04d359 100644 --- a/internal/cli/trust.go +++ b/internal/cli/trust.go @@ -44,7 +44,7 @@ func runTrust(args []string, stdout io.Writer, stderr io.Writer, deps appDeps) i func trustCurrentDir(stdout io.Writer, stderr io.Writer, deps appDeps) int { cwd, err := deps.getwd() if err != nil { - return writeAppError(stderr, redaction.ErrorMessage(fmt.Errorf("resolve workspace: %w", err), redaction.Options{}), exitCrash) + return writeAppError(stderr, redaction.ErrorMessage(fmt.Errorf("resolve workspace: %s", err), redaction.Options{}), exitCrash) } if err := workspacetrust.Trust(cwd); err != nil { return writeAppError(stderr, redaction.ErrorMessage(err, redaction.Options{}), exitCrash) @@ -86,7 +86,7 @@ func trustRemove(args []string, stdout io.Writer, stderr io.Writer, deps appDeps case 0: cwd, err := deps.getwd() if err != nil { - return writeAppError(stderr, redaction.ErrorMessage(fmt.Errorf("resolve workspace: %w", err), redaction.Options{}), exitCrash) + return writeAppError(stderr, redaction.ErrorMessage(fmt.Errorf("resolve workspace: %s", err), redaction.Options{}), exitCrash) } target = cwd case 1: