Skip to content

A2A 1.0 extraction: follow-up hardening and test-vector expansion #2966

Description

@bokelley

Follow-ups from the expert-review rounds on the A2A 1.0 extraction spec (bokelley/a2a-1.0-update branch, PR pending). The branch ships the 1.0 wire-format migration plus immediate security/correctness fixes. Items below are valuable but non-blocking — group them into a post-merge hardening pass.

Wrapper policy — status-message asymmetry

Current spec: {response: {...}} single-key wrapper rejection applies only to artifact DataParts (final states), not to DataParts in status.message.parts (interim states or final-state fallback). A server bug emitting wrappers in interim updates currently slips through silently. Decide:

  • Hoist wrapper detection into a shared helper applied at every return part.data site; or
  • Document the asymmetry as intentional (interim is lightweight progress, not normative schema surface).

Related: cross-repo conflict with adcp-client-python (see adcp-client-python#263) where the Python client unwraps rather than rejects.

Prototype-pollution test hardening

Existing vector proto-pollution-payload only exercises __proto__, which JSON.parse already handles correctly. The realistic threat is downstream Object.assign/spread. Add:

  • A vector with constructor: { prototype: { isAdmin: true } }.
  • A test that simulates Object.assign({}, extracted) and asserts no pollution on ({}).isAdmin.

Concrete size + timeout bounds

Extraction spec mentions "e.g., 1 MB" for DataPart size. Tighten for raw FileParts and challenge_url fetches:

  • raw decoded: suggest 5 MB cap.
  • challenge_url fetch (if server-side validation): 256 KB response, 10 s timeout, redirect limit 3.

Intermediary-injection — actionable guidance

Current text ("validate artifact part count matches expectations") isn't implementable since buyers rarely know the expected count. Either:

  • Flag as future work pending artifact signing or header-based checksums (X-AdCP-Parts-Hash); or
  • Replace with more practical advice (e.g., "accept only from authenticated peer with validated agent card").

Test-vector expansion

  • 100+ DataPart boundary vector — locks in "last wins at scale" and guards against accidental O(n²) regression.
  • Two-key / empty-key / {"": {...}} malformed-envelope vectors — behavior is correct in code but not asserted.
  • { task: { ... state: TASK_STATE_REJECTED ... } } and { statusUpdate: { ... state: TASK_STATE_AUTH_REQUIRED ... } } combinatorial vectors — currently envelope-wrapping and new states are tested separately, not combined.
  • Wrapper-in-status-message vector — whether to throw or extract is the policy question above, but add a vector once decided.

Vector quality-of-life

  • path field (artifact / status_message / none) is documentation-only; add an assertion that the actual extraction path matches, or drop the field.
  • Timestamps still mixed 2025 vs 2026 — standardize on ISO-8601 UTC with ms precision across all vectors.

extractTextPartFromArtifacts asymmetry

TextPart uses first-match (.find) while DataPart uses last-match (.filter().at(-1)). Defensible (text is presentational, data is authoritative) but not documented. Add one-line comment or make symmetric.

Origin of follow-ups

Flagged across four expert-review passes during the 1.0 migration. Protocol and product reviewers gave "ship it" on the main branch; code and security reviewers found additional hardening opportunities.

🤖 Filed with Claude Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions