Skip to content

fix(auth): reject non-positive and non-finite token exchange expires_in - #3735

Open
jaideeppyne wants to merge 1 commit into
openai:mainfrom
jaideeppyne:fix/workload-identity-expires-in-validation
Open

fix(auth): reject non-positive and non-finite token exchange expires_in#3735
jaideeppyne wants to merge 1 commit into
openai:mainfrom
jaideeppyne:fix/workload-identity-expires-in-validation

Conversation

@jaideeppyne

Copy link
Copy Markdown

Changes being requested

WorkloadIdentityAuth._validate_expires_in (the base subject-token exchange path used by the JWT / GCP / Azure workload-identity flows) accepted any int/float and returned float(expires_in) without validation. Because bool subclasses int, a true/false value was silently treated as a 1/0 second lifetime; negative, zero, NaN, and infinite values were also accepted, and a value that overflows float() (e.g. 10**400) raised an uncaught OverflowError surfaced to the caller as a generic connection error.

An infinite/overflowing lifetime is the most harmful case: _needs_refresh() never fires, so the client keeps reusing a token indefinitely after it has expired server-side, producing persistent auth failures that never self-heal.

The X.509 workload-identity path already enforces this contract (_x509._as_finite_float + test_x509_rejects_nonpositive_or_nonnumeric_expiration, which rejects [0, -1, True, "3600", None, 10**400]). This applies the same rule — a positive, finite expires_in is required — to the base path. X.509 behavior is unchanged; it keeps its own override.

Added a parametrized regression test (test_workload_identity_rejects_nonpositive_or_nonnumeric_expiration) mirroring the existing X.509 test. Fails before the change, passes after; the full auth/x509 suite (390 tests) passes and ruff is clean.

Additional context & links

None.

  • I understand that this repository is auto-generated and my pull request may not be merged

The base `WorkloadIdentityAuth._validate_expires_in` accepted any
`int`/`float` and returned `float(expires_in)` unchecked. Because
`bool` is a subclass of `int`, a `true`/`false` value was silently
treated as a 1/0 second lifetime, and negative, zero, NaN or infinite
values were accepted as well. An infinite (or overflowing) lifetime is
especially harmful: `_needs_refresh()` never fires, so the client keeps
reusing a token indefinitely after it has expired server-side.

The X.509 workload-identity path already validates this correctly (see
`_x509._as_finite_float` and the `test_x509_rejects_nonpositive_or_nonnumeric_expiration`
regression). Apply the same contract to the base subject-token exchange
path (JWT / GCP / Azure) so a positive, finite `expires_in` is required.
@jaideeppyne
jaideeppyne requested a review from a team as a code owner August 25, 2026 11:21

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b64ae6602

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/test_auth.py


@respx2.mock
@pytest.mark.parametrize("expires_in", [0, -1, True, "3600", None, 10**400])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Cover non-finite expirations on both client paths

The regression matrix neither includes NaN/positive or negative infinity—the non-finite values this change is intended to reject—nor exercises the AsyncOpenAI public path. Consequently, removing the math.isfinite guard or breaking async error propagation would leave this suite passing; add explicit non-finite cases and an asynchronous invalid-expiration test, as authentication changes require focused synchronous and asynchronous regression coverage.

AGENTS.md reference: AGENTS.md:L41-L45

Useful? React with 👍 / 👎.

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