Skip to content

Fix chat to use all active goals instead of only the first one#4778

Merged
aaravgarg merged 5 commits intomainfrom
fix/chat-use-all-goals
Feb 12, 2026
Merged

Fix chat to use all active goals instead of only the first one#4778
aaravgarg merged 5 commits intomainfrom
fix/chat-use-all-goals

Conversation

@aaravgarg
Copy link
Collaborator

Summary

  • Chat prompt now includes all active goals (up to 3) instead of only the first one
  • Goal progress extraction from chat messages now checks against all active goals
  • Fixed get_goal_advice to properly look up goals by ID instead of only working for the first active goal

Test plan

  • All 20 backend tests pass
  • Verify chat prompt includes multiple goals when user has more than one active goal
  • Verify goal progress extraction updates the correct goal when multiple are active

🤖 Generated with Claude Code

aaravgarg and others added 5 commits February 12, 2026 23:36
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aaravgarg aaravgarg merged commit 3e33268 into main Feb 12, 2026
1 check passed
@aaravgarg aaravgarg deleted the fix/chat-use-all-goals branch February 12, 2026 18:14
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to handle multiple active user goals in chat and goal-related functions. While it introduces valuable bug fixes and feature enhancements in get_goal_advice and _get_agentic_qa_prompt, it critically introduces Prompt Injection vulnerabilities by embedding unsanitized user data (goal titles and chat messages) directly into LLM prompts. This is particularly concerning in the main chat agent, which has access to sensitive tools. Furthermore, the extract_and_update_goal_progress function has a performance issue due to making an LLM call for each active goal. It is recommended to sanitize all user inputs to LLM prompts and refactor extract_and_update_goal_progress to use a single, more efficient LLM call.

Comment on lines +249 to 261
for goal in goals:
goal_title = goal.get('title', '')
current_value = goal.get('current_value', 0)
target_value = goal.get('target_value', 10)
goal_type = goal.get('goal_type', 'numeric')

prompt = f"""Analyze this message to see if it mentions progress toward this goal:
prompt = f"""Analyze this message to see if it mentions progress toward this goal:

Goal: "{goal_title}"
Goal Type: {goal_type}
Current Progress: {current_value} / {target_value}

User Message: "{text[:500]}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The extract_and_update_goal_progress function embeds untrusted user messages and goal titles directly into a prompt, leading to a Prompt Injection vulnerability. An attacker can use this to manipulate the LLM's extraction logic, potentially leading to unauthorized updates of goal progress. This also poses a risk of indirect prompt injection. Additionally, the current implementation makes an LLM call for each active goal, which is inefficient and costly. It is crucial to sanitize user inputs (like text and goal_title) before embedding them into LLM prompts to prevent prompt breakout. Furthermore, consider refactoring this to make a single, more efficient LLM call that processes all active goals at once, rather than individual calls.

        for goal in goals:
            goal_title = goal.get('title', '').replace('"', '\"')
            current_value = goal.get('current_value', 0)
            target_value = goal.get('target_value', 10)
            goal_type = goal.get('goal_type', 'numeric')

            prompt = f"""Analyze this message to see if it mentions progress toward this goal:

Goal: "{goal_title}"
Goal Type: {goal_type}
Current Progress: {current_value} / {target_value}

User Message: "{text[:500].replace('"', '\"')}"""

Comment on lines +468 to +472
for g in user_goals:
g_title = g.get('title', '')
g_current = g.get('current_value', 0)
g_target = g.get('target_value', 0)
goals_lines.append(f'- "{g_title}" (Progress: {g_current}/{g_target})')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The application constructs a system prompt by directly embedding user-supplied goal titles into an XML-like structure without proper sanitization. If a goal title contains malicious content (e.g., closing tags like </user_goals> followed by new instructions), it can break out of the intended context and manipulate the LLM's behavior. This is a Prompt Injection vulnerability that could allow an attacker to bypass security constraints or exfiltrate sensitive information using the LLM's available tools (such as Gmail or web search tools).

Suggested change
for g in user_goals:
g_title = g.get('title', '')
g_current = g.get('current_value', 0)
g_target = g.get('target_value', 0)
goals_lines.append(f'- "{g_title}" (Progress: {g_current}/{g_target})')
for g in user_goals:
g_title = g.get('title', '').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;')
g_current = g.get('current_value', 0)
g_target = g.get('target_value', 0)
goals_lines.append(f'- "{g_title}" (Progress: {g_current}/{g_target})')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant