Commit Graph
3 Commits
Author SHA1 Message Date
Elizabeth ThompsonandClaude Opus 4.8 eee8f3b3f4 fix(embedded): fail closed when the guest-user check can't resolve a principal
Follow-up to #43834. That change guarded is_sanitization_required() so a
raising user loader could no longer turn error responses into bare 500s,
but it failed *open*: when the guest-user check raised it returned False
("do not sanitize"), which can disclose raw engine errors to a genuine
embedded guest.

The check can raise for a resolvable guest, not only an unresolvable
anonymous one: get_guest_user_from_token() calls find_role() (a metadata-DB
round trip) outside the request loader's try/except, and is_guest_user()
consults the EMBEDDED_SUPERSET feature hook first. On a request whose DB
session is already broken -- exactly the state a SQLAlchemyError handler
runs in -- a valid guest token then yields the raw driver error instead of
a redacted message.

Make the fallback incapable of raising and fail closed for anyone
presenting a token:

- is_sanitization_required(): on failure, inside a request context fall
  back to whether the request carries a guest token (reading the header or
  form field cannot raise); redact if it does, leave genuinely anonymous
  errors untouched. Outside a request context (Celery worker under
  override_user) fail closed and redact, since the payload is delivered to
  the embedded viewer. Reworded the docstring as an availability-over-
  confidentiality trade-off rather than a definitional truth.

- Resolve the decision once and thread it down: add an optional
  `required` param to the sanitize_* helpers so a list is looked up a
  single time instead of once per error (fixes the N+1 loader calls and
  WARNING log-spam on multi-error responses).

- charts/data/api.py: replace the raw outer is_guest_user() with the
  guarded, once-resolved decision and reuse it for both the stacktrace pop
  and the message sanitization, so the block can no longer half-redact
  (drop the stacktrace while leaking the raw error).

- views/error_handling.py: give the last-resort show_unexpected_exception
  the same try/except FileNotFoundError fallback its siblings have, so a
  missing 500.html no longer collapses the response to a bare 500 with no
  SIP-40 body.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Elizabeth Thompson <eschutho@gmail.com>
2026-09-04 20:05:29 +00:00
Elizabeth ThompsonandClaude Opus 4.8 cceb52e776 fix(embedded): don't let guest-user check turn error responses into 500s (#43834)
Signed-off-by: Elizabeth Thompson <eschutho@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 21:18:43 -07:00
Mehmet Salih Yavuz daf1718b44 fix(embedded): redact database errors in API responses to guest users (#42796) 2026-08-10 18:45:20 +03:00