Skip to content

security(websocket): agent RuntimeError text is surfaced verbatim to public chat visitors #1479

Description

@codeacme17

Problem

When an agent turn fails with a RuntimeError, its text is sent to the client twice — as the message_rejected ack and as an error event — and the frontend renders both verbatim:

  • src/xagent/web/api/websocket.py: message = f"Runtime error: {str(e)}" in _handle_chat_message_unserialized and in handle_execute_task.
  • frontend/src/contexts/app-context-chat.tsx:882 reads the string unchanged and :5578 renders it as an assistant error bubble.

The same handler serves widget and share connections, so an anonymous visitor can receive whatever a runtime failure happened to interpolate — provider payloads, file paths, driver messages.

Why this is not just a bug fix

Surfacing that text is a deliberate, tested contract: tests/web/api/test_websocket_owner_actor.py:2260 asserts "inject failed" in rejected[0]["message"], i.e. an agent post_user_message failure must reach the sender. For an authenticated operator debugging their own task, that is useful. For an anonymous widget visitor, it is disclosure.

So the fix is not "redact it" — it is deciding who may see it, which is a product call:

  • redact for public widget/share connections and keep the current text for authenticated owners, or
  • introduce a safe_for_display / stable error-code field on the wire and localize codes on the client, keeping raw text out of every path.

Already done

#1472 fixed the neighbouring half: incidental ValueError/KeyError/TypeError text is now replaced with CLIENT_SAFE_VALIDATION_ERROR, while messages genuinely written for the sender raise ClientVisibleValidationError and keep their wording (tests/web/api/test_websocket_client_safe_errors.py). The RuntimeError path was left untouched on purpose, because changing it means changing the pinned contract above.

Context

Raised as finding N3 in the #1472 review. Related: #1468, #1467.

Metadata

Metadata

Assignees

Labels

P0bugSomething isn't workingsecuritySecurity-sensitive defect or hardening

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions