Skip to content

fix: validate task state transitions (block terminal escape) - #1182

Open
ez-lbz wants to merge 2 commits into
a2aproject:mainfrom
ez-lbz:fix/state-transition-validation
Open

fix: validate task state transitions (block terminal escape)#1182
ez-lbz wants to merge 2 commits into
a2aproject:mainfrom
ez-lbz:fix/state-transition-validation

Conversation

@ez-lbz

@ez-lbz ez-lbz commented Aug 10, 2026

Copy link
Copy Markdown

What changed

1. Validate task state transitions before persisting status updates

Problem: TaskManager.save_task_event() (src/a2a/server/tasks/task_manager.py) blindly overwrote the task status with task.status.CopyFrom(event.status) for every TaskStatusUpdateEvent. A misbehaving or malicious agent could move a task that is already in a terminal state (COMPLETED/CANCELED/FAILED/REJECTED) back to SUBMITTED (or to another state), rewriting the persisted terminal outcome. active_task.py:571 was already guarded (if task.status.state not in TERMINAL_TASK_STATES) and needed no change.

Fix (src/a2a/server/tasks/task_manager.py):

  • Added TERMINAL_TASK_STATES and validate_state_transition(current_state, new_state), which raises InvalidAgentResponseError when a terminal state would transition to any different state (including back to SUBMITTED). Re-persisting the same terminal state is tolerated for idempotency, and all forward transitions (SUBMITTED→WORKING→terminal, interrupted states, etc.) are unaffected.
  • save_task_event() now calls validate_state_transition() before task.status.CopyFrom(...). Both the V1 path (ResultAggregator → TaskManager) and the V2 path (ActiveTask EventConsumer → TaskManager) flow through this single chokepoint.

Testing

  • ./.venv/Scripts/python -m pytest tests/server/tasks/test_task_manager.py -q29 passed (includes new tests: parametrized rejection of every terminal→other transition, acceptance of legal forward/idempotent transitions, and an end-to-end save_task_event regression test asserting a completed task cannot be moved back to SUBMITTED and the store is unchanged).
  • ./.venv/Scripts/python -m pytest tests/server/request_handlers/ tests/server/agent_execution/ tests/server/tasks/ tests/server/events/ -q551 passed, 90 skipped, 3 xfailed (pre-existing xfails reference upstream issue [Feat]: Improve server concurrency architecture #869).
  • ./.venv/Scripts/python -m ruff check on modified files: clean.
  • Behavior change: status updates that would move a terminal task to a different state now fail with InvalidAgentResponseError (-32006) instead of silently overwriting the persisted state. All legitimate agent flows (including REJECTED/CANCELED) are unaffected.

@ez-lbz
ez-lbz requested a review from a team as a code owner August 10, 2026 16:09
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

🧪 Code Coverage (vs main)

⬇️ Download Full Report

Base PR Delta
src/a2a/server/events/event_queue_v2.py 91.79% 91.28% 🔴 -0.51%
src/a2a/server/tasks/task_manager.py 98.68% 98.74% 🟢 +0.06%
src/a2a/utils/telemetry.py 91.47% 90.70% 🔴 -0.78%
Total 93.00% 92.98% 🔴 -0.02%

Generated by coverage-comment.yml

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