[Bug]: Agent card signature verification raises raw binascii.Error on a malformed protected header instead of SignatureVerificationError
Maintainer thường phản hồi trong vòng 2 ngày
@rohityan đang làm issue này rồi.
Từ ngày 9/10/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
What happened?
create_signature_verifier's verification loop (src/a2a/utils/signing.py:139-159) only catches PyJWTError:
for agent_card_signature in agent_card.signatures:
try:
protected_header_json = base64url_decode(
agent_card_signature.protected.encode('utf-8')
).decode('utf-8') # may raise binascii.Error / UnicodeDecodeError
protected_header = json.loads(protected_header_json) # may raise JSONDecodeError
...
verification_key = key_provider(kid, jku) # may raise anything (e.g. network errors)
jwt.decode(...)
break
except PyJWTError:
continue
agent_card_signature.protected is an attacker-controlled field. A malformed value makes base64url_decode raise a raw binascii.Error, which escapes the verifier entirely — violating the module's own contract: the canonicalization step just above explicitly converts failures to InvalidSignaturesError "so every failure on this path is a SignatureVerificationError", but the per-signature loop does not.
It also breaks the documented multi-signature semantic ("succeeds if at least one signature is valid"): a card holding [malformed_signature, valid_signature] raises instead of verifying.
Additionally, any exception raised by key_provider (e.g. a network failure while fetching the JKU) aborts the whole loop for the same reason.
Reproduction
from a2a.types.a2a_pb2 import AgentCard, AgentCardSignature
from a2a.utils.signing import (
SignatureVerificationError,
create_signature_verifier,
)
verifier = create_signature_verifier(
key_provider=lambda kid, jku: b'dummy-key',
algorithms=['RS256'],
)
card = AgentCard(
name='t',
version='1.0',
signatures=[
AgentCardSignature(protected='!!!not-base64url!!!', signature='aaa')
],
)
try:
verifier(card)
except SignatureVerificationError as e:
print(f'contract respected: {type(e).__name__}: {e}')
except Exception as e:
print(f'CONTRACT BROKEN -> {type(e).__name__}: {e}')
Observed output:
CONTRACT BROKEN -> Error: Invalid base64-encoded string: number of data characters (13) cannot be 1 more than a multiple of 4
Expected behavior
Every failure on the verification path should surface as SignatureVerificationError (per the contract established at signing.py:124-128), and a malformed signature should count as "invalid" so remaining signatures are still attempted.
Suggested fix
Widen the per-signature except clause, e.g.:
except (PyJWTError, ValueError, binascii.Error, UnicodeDecodeError):
continue
or wrap the loop body so parse/key-provider failures are logged and treated as an invalid signature. This is non-breaking for correct inputs and only converts escapes into the documented error type.
Happy to submit a PR with tests.
Code of Conduct
- I agree to follow this project's Code of Conduct
- Ngôn ngữ chính
- Python
- Star
- 2.2k
- Fork
- 509
- Merge trung bình
- 3 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 43
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của a2aproject/a2a-python
-
[Bug]: REST task/request id sanitizationCó thể đã có người làm @Linux2010 đã nhận 104 ngày trước. Đang mởmaintainers-only
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
a2aproject/a2a-python#805 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[Bug]: Framework-written FAILED status drops status.timestamp, persisting last_updated as NULLCó thể đã có người làm @rohityan đã nhận 1 ngày trước. Đang mở
a2aproject/a2a-python#1331 · 2 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[Bug]: message/send hangs forever when the AgentExecutor returns without producing eventsCó thể đã có người làm @rohityan đã nhận 1 ngày trước. Đang mở
a2aproject/a2a-python#1330 · 2 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Whole numbers in a data Part are returned as floats (e.g. 4326 becomes 4326.0)Có thể đã có người làm @rohityan đã nhận 1 ngày trước. Đang mở
a2aproject/a2a-python#1328 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[Feat]: Cluster mode: detect and recover tasks abandoned by a crashed replica (heartbeat/lease)Có thể đã có người làm @ishymko đã nhận 1 ngày trước. Đang mởcomponent: server status: needs review
a2aproject/a2a-python#1324 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của a2aproject/a2a-python
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
topoteretes/cognee#5647 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Sendspin/sendspin-python-cli#291 ·
Maintainer thường phản hồi trong vòng 6 ngày
-
Assertion-shape guard fails on development: vacuous recorded-iteration assertion in the assetLinks batch_get helper testCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
awslabs/visual-asset-management-system#414 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
modelcontextprotocol/python-sdk#3670 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
aicell-lab/bioengine#232 ·
Maintainer thường phản hồi trong vòng 1 ngày