Skip to content

fix(a2a): parse quoted values and escapes in WWW-Authenticate headers - #9111

Open
Mehedi Hasan (Mahdi-Hasan) wants to merge 1 commit into
crewAIInc:mainfrom
Mahdi-Hasan:fix/a2a-parse-www-authenticate
Open

Mehedi Hasan (Mahdi-Hasan) wants to merge 1 commit into
crewAIInc:mainfrom
Mahdi-Hasan:fix/a2a-parse-www-authenticate

Conversation

@Mahdi-Hasan

@Mahdi-Hasan Mehedi Hasan (Mahdi-Hasan) commented Nov 5, 2026 •

Copy link
Copy Markdown

Fixes #9108

parse_www_authenticate split the header with regexes that ignore quoting, so a comma inside a quoted value cut it short and created bogus challenges. It now tokenises with quote-aware parsing and handles escaped quotes, empty quoted values and bare schemes. Adds lib/crewai/tests/a2a/utils/test_auth_utils.py: 6 of 10 fail on main, all pass now; the 111 tests in lib/crewai/tests/a2a pass; ruff clean.


Note

Medium Risk
Changes how 401 WWW-Authenticate challenges are parsed for A2A retry logic; behavior shifts for edge cases but aligns with intended header semantics.

Overview
parse_www_authenticate no longer splits WWW-Authenticate with regexes that treat commas inside quoted strings as challenge separators. It now scans the header with quote-aware param matching, unescapes \" in quoted values, and still records schemes with no parameters (e.g. bare Bearer or Negotiate).

New patterns (_NAME_CHARS, separator/param/scheme matchers, _QUOTED_PAIR_PATTERN) replace the old _SCHEME_PATTERN / _PARAM_PATTERN pair. lib/crewai/tests/a2a/utils/test_auth_utils.py adds coverage for multi-challenge headers, commas in quotes, escapes, empty quoted values, and whitespace-only headers.

This parser feeds retry_on_401, so more accurate challenge dicts should reduce mis-parsed 401 metadata during A2A auth retries.

Reviewed by Cursor Bugbot for commit ba8e488. Bugbot is set up for automated code reviews on this repo. Configure here.

parse_www_authenticate split the header with regexes that ignored quoting.
A comma inside a quoted value, such as the sentence RFC 6750 allows in
error_description, cut the value at the comma and turned the following
words into extra challenges ("which", "is"). An empty quoted value came
back as None, an escaped quote ended the value early, and a scheme sent
without parameters ("Bearer") was dropped.

Read the header with a small scanner instead: quoted strings with
backslash escapes, comma separated parameters, and one challenge per
scheme token, including schemes with no parameters. Unquoted values and
the returned shape are unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@strix-security

strix-security Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Strix Security Review

✅ No open security findings.

PR summary: Rewrites `parse_www_authenticate` in the A2A auth utils as a quote-aware tokenizer so commas inside quoted values, escaped quotes, empty quoted values and bare schemes parse correctly, and adds a unit-test module covering those cases.

Review summary

This PR replaces the two regex finditer passes with a hand-rolled tokenizing loop and a narrower RFC 7235 token charset. No security issue was found. The parsed dictionary does not drive any authentication decision: its single consumer is retry_on_401 in the same module, which reads only params.get("realm") into a RuntimeError string on a branch that cannot execute while challenges are populated, so the more permissive parsing changes no credential choice, scheme/realm check, digest challenge handling, retry logic or outgoing header. The new regexes are also not attacker-abusable: the quoted-string alternatives are disjoint so backtracking is linear, loop progress is guaranteed on every path, and the unescaping helper only deletes backslashes, so it cannot synthesise characters the peer did not send. Measurements on adversarial headers through 1 MB stayed linear with no exceptions, and every edge input (empty, whitespace-only, bare scheme, unterminated quote, trailing backslash, control and non-ASCII bytes) parses without raising. Only cosmetic parser semantics remain (for example token68 values such as abc.def== landing in the parameter branch, and parameters appearing before the first scheme becoming phantom challenge keys), with no reachable effect today.

Ruled out (3)
  • Can a malicious WWW-Authenticate header make the new tokenizer hang, blow up CPU/memory, or raise an unhandled exception?
    The quoted-string alternatives are disjoint so backtracking stays linear, `position` strictly increases on every loop path (verified exhaustively over short inputs and fuzzed over 4,988 random ones), and adversarial headers up to 1 MB were measured at a flat ~0.75 µs/char with no exceptions.
  • Does the parse result influence credential selection, realm/scope checks, digest handling, retry decisions or outgoing headers, so that the looser parsing coul…
    The only call site is `retry_on_401`, which uses the challenges solely to build an error message on a branch that is unreachable while `last_challenges` is non-empty; `apply_auth` writes fixed credentials, digest challenges are parsed by httpx itself, and the store key is derived from the auth obje…
  • Can the escaped-quote unescaping turn attacker text into a value containing control characters that the input did not contain?
    `_QUOTED_PAIR_PATTERN.sub(r"\1", quoted)` only removes backslashes without decoding escape sequences, so the output character set is always a subset of the input.

Review 1 on this PR · ba8e488 · requested Nov 5 09:10 UTC when the PR was opened


Reviewed by Strix
Re-run review · Configure security review settings

This branch has not been deployed

No deployments
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] parse_www_authenticate mangles quoted values that contain commas

1 participant