fix(tool_runner): avoid leaking tool exception details to LLM (CWE-209) - #814
Open
andesyteoss wants to merge 1 commit into
Open
fix(tool_runner): avoid leaking tool exception details to LLM (CWE-209)#814andesyteoss wants to merge 1 commit into
andesyteoss wants to merge 1 commit into
Conversation
Exception messages raised by tool implementations were embedded verbatim into the ToolMessage.content returned to the agent. Since ToolMessage content is fed back into the LLM and, in Streamlit-based frontends, rendered directly to the end user, raw exception text could disclose sensitive internals (file paths, stack-trace fragments, connection strings, credentials, internal hostnames/IPs) that an attacker can trigger by intentionally causing tool failures. Log full exception details server-side via logger.exception and return a generic error message (including only the exception class name) to the caller.
maciejmajek
approved these changes
Jul 21, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #814 +/- ##
=======================================
Coverage 73.19% 73.19%
=======================================
Files 82 82
Lines 3582 3582
=======================================
Hits 2622 2622
Misses 960 960 ☔ View full report in Codecov by Harness. |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Fix a CWE-209 (Generation of Error Message Containing Sensitive Information) issue in
ToolRunnerwhere the raw exception object raised by a tool is embedded verbatim into theToolMessagereturned to the LLM/user.Proposed Changes
In
src/rai_core/rai/agents/langchain/core/tool_runner.py, when a tool invocation raises, the exception's stringified form was previously written into theToolMessage.contentfield:Because the
ToolMessageis returned to the caller (and typically fed back to the LLM and any downstream conversation surface), any sensitive data carried by the exception — file paths, stack traces, connection strings, credentials embedded in error messages by underlying libraries (e.g.psycopg2,requests,paramiko), internal IP addresses, ROS 2 topic/service internals — is exposed to whoever can observe the conversation.This PR:
self.logger.info(...)toself.logger.exception(...), so operators still see the full traceback and message in logs (where it belongs).RuntimeError,ValueError) — enough for the LLM to decide whether to retry or reformulate, but not enough to leak internals.Issues
No pre-existing issue; filing this directly as a small security fix.
Testing
Reproduction (before the fix):
SUPER_SECRET_PW, the internal host10.0.0.5, and the DB name.Tool 'leaky_tool' failed with RuntimeError. Please try again or rephrase your request.— no secret, host, or connection string. The full traceback is still emitted vialogger.exception, so operators lose no diagnostic information.The change is confined to the exception branch of the tool-invocation loop; the success path and the existing
ValidationErrorbranch are untouched.Security analysis
ToolRunner._funcinsrc/rai_core/rai/agents/langchain/core/tool_runner.py(the genericexcept Exception as e:handler at what was line 107).str(e)interpolated intoToolMessage.content→ returned in the agent's message list → surfaced to the LLM prompt and any UI/log that renders the conversation.ToolRunnerraises an exception whose message contains sensitive data — common in practice because DB drivers, HTTP clients, and SSH libraries routinely embed hosts/paths/credentials in exception strings; (2) an attacker can observe LLM output (either directly as a user, or via a lower-privilege channel that receives the assistant's replies).Adversarial review
Before submitting we tried to disprove this. We checked whether
RunnableCallableor LangChain sanitisesToolMessage.contentbefore returning it — it does not; the content is passed through unchanged. We checked whether there is a parallel error path elsewhere inToolRunnerthat would still leak — the only other error branch handlesValidationErrorfor tool-arg parsing and echoes the validator's message, which is bounded to schema info and not the same class of leak; it is out of scope for this patch. We considered whether preconditions already grant the attacker the leaked info — they don't: a user asking a robotics agent to call a database or perception tool does not, by that act, gain access to the DB's connection string. The finding stands.Notes for reviewers
ToolMessageshape is unchanged, only itscontentstring is now generic.