Address greptile round 2: sanitize errors, defense-in-depth allowlist, revert tsconfig

- Sanitize error messages: generic 'An internal error occurred' sent to client,
  full exception logged server-side via verbose_proxy_logger
- Defense-in-depth: _process_tool_call validates fn_name against role-based
  allowlist before dispatch (even though LLM only receives allowed tools)
- Revert tsconfig.json jsx back to 'preserve' (Next.js recommended default)

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-02-24 23:58:58 +00:00
parent 84df54cc78
commit 1aca6874da
3 changed files with 15 additions and 7 deletions

View file

@ -449,14 +449,16 @@ async def _process_tool_call(
"""Execute a single tool call, yielding SSE events for status."""
fn_name = tc.function.name
fn_args = json.loads(tc.function.arguments)
allowed_names = {t["function"]["name"] for t in get_tools_for_role(is_admin)}
handler = TOOL_HANDLERS.get(fn_name)
if not handler:
if fn_name not in allowed_names or not handler:
chat_messages.append(
{
"role": "tool",
"tool_call_id": tc.id,
"content": f"Unknown tool: {fn_name}",
"content": f"Tool not available: {fn_name}",
}
)
return
@ -475,8 +477,9 @@ async def _process_tool_call(
)
yield _sse({**tool_event_base, "status": "complete"})
except Exception as e:
tool_result = f"Error: {e}"
yield _sse({**tool_event_base, "status": "error", "error": str(e)})
verbose_proxy_logger.error("Tool %s failed: %s", fn_name, e)
tool_result = f"Error fetching {handler['label']}. Please try again."
yield _sse({**tool_event_base, "status": "error"})
chat_messages.append(
{"role": "tool", "tool_call_id": tc.id, "content": tool_result}
@ -542,4 +545,9 @@ async def stream_usage_ai_chat(
except Exception as e:
verbose_proxy_logger.error("AI usage chat failed: %s", e)
yield _sse({"type": "error", "message": str(e)})
yield _sse(
{
"type": "error",
"message": "An internal error occurred. Please try again.",
}
)

View file

@ -313,7 +313,7 @@ class TestStreamUsageAiChat:
error_events = [e for e in events if e["type"] == "error"]
assert len(error_events) == 1
assert "LLM error" in error_events[0]["message"]
assert "internal error" in error_events[0]["message"].lower()
@pytest.mark.asyncio
async def test_non_admin_enforces_user_id(self):

View file

@ -14,7 +14,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"jsx": "preserve",
"incremental": true,
"plugins": [
{