Skip to content

fix: reject whitespace-only task_summary in orchestrator context capture (#459) - #580

Open
Deez-Automations wants to merge 1 commit into
GenAI-Security-Project:mainfrom
Deez-Automations:fix/orchestrator-whitespace-summary-459
Open

fix: reject whitespace-only task_summary in orchestrator context capture (#459)#580
Deez-Automations wants to merge 1 commit into
GenAI-Security-Project:mainfrom
Deez-Automations:fix/orchestrator-whitespace-summary-459

Conversation

@Deez-Automations

Copy link
Copy Markdown

Fixes #459.

The bug

OrchestratorAgent._capture_agent_context decides whether to store an upstream agent's task_summary for propagation to downstream agents (via _enrich_with_prior_context, which injects every stored (agent_label, summary) pair verbatim into the next agent's task description under a "Prior workflow context" header). The guard was if summary: — a whitespace-only string (" ") is truthy in Python, so it passed the guard and got stored and propagated as pure noise.

Per the issue: this wastes tokens, and the guard being satisfiable by a non-empty-but-content-free string is a soft spot a prompt-injection payload could exploit to slip something past it undetected.

Scope check

Verified against current source before writing anything: the issue's line numbers (421-422) match exactly, and this is the sole call site of this truthiness pattern in the file — the two other task_summary reads (an event-emission call, already [:200]-truncated, and a logging call) don't gate storage, so neither needed the fix. All 6 delegation methods (onboarding, invoice, fraud, payments, system_maintenance, communication agents) funnel through this one method, so the single fix covers all 6.

Fix

# before
if summary:

# after
if isinstance(summary, str) and summary.strip():

Went one step past the issue's own suggested summary and summary.strip(). Security review caught that .strip() alone would raise AttributeError on a truthy non-string task_summary — today that's unreachable in practice (schema-typed as "string" under a strict LLM tool-call contract in base.py's complete_task schema), verified independently against that schema before applying, but relying on an external API contract alone for local crash-safety doesn't match this repo's own boundary-validation convention. Added the isinstance check so a violation of that invariant fails safe (summary just isn't stored) instead of turning into an AttributeError that burns one of the agent's limited delegation retries.

A real summary with incidental leading/trailing whitespace is still stored verbatim — only the truthiness check changed, the stored value itself is untouched.

Tests

9 new tests in tests/unit/agents/test_orchestrator_whitespace_context.py (no prior test file existed for OrchestratorAgent at all): whitespace-only, empty-string, missing-key, tab/newline-only, non-string, a real summary, a real summary with incidental whitespace kept verbatim, plus two integration tests through _enrich_with_prior_context confirming the polluted context never reaches a downstream task description. Confirmed RED before the fix (4/8 failed, exactly the whitespace-related cases), GREEN after.

Test plan

…ure (GenAI-Security-Project#459)

OrchestratorAgent._capture_agent_context used `if summary:` to decide
whether to store an upstream agent's task_summary for downstream
propagation via _enrich_with_prior_context. A whitespace-only string
("   ") is truthy in Python, so it passed the guard and got injected
verbatim into every subsequent agent's task description as pure noise
under a "Prior workflow context (include all directives when acting)"
header -- wasted tokens, and per the issue, a guard a prompt-injection
payload could hide behind (non-empty but content-free).

Fixed to `if isinstance(summary, str) and summary.strip():`. The
isinstance check goes one step past the issue's own suggested
`summary and summary.strip()`: task_summary is only guaranteed to be a
string today because it's schema-typed under a strict LLM tool-call
contract (base.py's complete_task schema), not by any local check --
`.strip()` alone would raise AttributeError on a truthy non-string,
converting "store nothing" into an unrelated delegation-attempt
failure. Security review caught this; verified independently against
the schema before applying.

A real summary with incidental leading/trailing whitespace is still
stored verbatim (not stripped) -- only the truthiness check changed,
not the stored value.

9 new tests in test_orchestrator_whitespace_context.py: whitespace-only,
empty-string, missing-key, tab/newline-only, non-string, a real summary,
a real summary with incidental whitespace kept verbatim, and two
integration tests through _enrich_with_prior_context confirming the
polluted context never reaches a downstream task description.
Copilot AI lite review requested due to automatic review settings August 20, 2026 17:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

Bug_202_EVALUATE: Test Case ORCH-QA-001 — Whitespace-only task_summary stored in _workflow_context

2 participants