Skip to content

fix(auth): parse hostname for mTLS and PSC endpoint certificate rotat… - #18153

Open
attharva-24 wants to merge 1 commit into
googleapis:mainfrom
attharva-24:fix-mtls-url-check
Open

fix(auth): parse hostname for mTLS and PSC endpoint certificate rotat…#18153
attharva-24 wants to merge 1 commit into
googleapis:mainfrom
attharva-24:fix-mtls-url-check

Conversation

@attharva-24

Copy link
Copy Markdown
Contributor

Fixes #18147
Follow-up to #17928

Description

This PR resolves two defects in the mTLS endpoint detection logic previously used in requests.py and urllib3.py:

  1. Eliminates False Positives: Replaces raw URL substring search (prefix in url) with proper hostname isolation via urllib.parse.urlsplit(url).hostname. Standard non-mTLS URLs containing mtls.googleapis.com in paths or query parameters (e.g. https://storage.googleapis.com/bucket/mtls.googleapis.com or https://logging.googleapis.com/v2/entries?filter=mtls.googleapis.com) will no longer trigger unnecessary certificate rotation on 401.
  2. Adds Private Service Connect (PSC) Support: Adds support for enterprise PSC custom mTLS domains (*.p.googleapis.com) and regional mTLS domains (*.rep.mtls.googleapis.com), ensuring certificate rotation functions correctly for PSC connections.
  3. Centralizes Endpoint Helper: Adds _mtls_helper.is_mtls_endpoint(url) shared across both requests and urllib3 transports, with lazy evaluation on 401 status codes.

Tests

  • Added TestIsMtlsEndpoint unit test suite in tests/transport/test__mtls_helper.py covering standard mTLS, PSC endpoints, regional endpoints, path/query substring traps, port numbers, and edge cases.
  • Added integration tests in tests/transport/test_requests.py and tests/transport/test_urllib3.py verifying cert rotation is skipped on non-mTLS URLs with matching substrings and triggered on PSC URLs.

@attharva-24
attharva-24 requested review from a team as code owners August 19, 2026 06:49

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request centralizes and improves mTLS endpoint detection by introducing the is_mtls_endpoint helper function in _mtls_helper.py, replacing previous substring-based checks in both the requests and urllib3 transports. It also adds comprehensive unit tests to verify the new endpoint detection and cert rotation logic. The review feedback highlights a potential TypeError in is_mtls_endpoint when handling bytes URLs, as calling endswith with string suffixes on a bytes hostname outside the try-except block will raise an exception. Decoding bytes inputs to str at the start of the function is recommended to ensure robust error handling.

Comment thread packages/google-auth/google/auth/transport/_mtls_helper.py Outdated
…ion (googleapis#18147)

* Isolate hostname using urllib.parse.urlsplit in _mtls_helper.is_mtls_endpoint
* Eliminate false positives on non-mTLS URLs containing mtls substrings in paths/queries
* Add support for Private Service Connect (*.p.googleapis.com) custom mTLS endpoints
* Update AuthorizedSession and AuthorizedHttp to use shared is_mtls_endpoint helper
* Add comprehensive unit tests in test__mtls_helper, test_requests, and test_urllib3

Fixes googleapis#18147
Follow-up to googleapis#17928
@parthea

parthea commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the mTLS endpoint detection logic by introducing a centralized is_mtls_endpoint helper in _mtls_helper.py and updating both requests and urllib3 transports to use it. It also adds comprehensive unit tests to verify the new helper and ensure cert rotation is skipped on non-mTLS URLs. The review feedback suggests improving the robustness of is_mtls_endpoint by handling non-string/non-bytes URL objects (such as urllib3.util.Url) to prevent them from being incorrectly classified as non-mTLS endpoints due to caught TypeErrors.

Comment on lines +866 to +876
if not url:
return False
if isinstance(url, bytes):
try:
url = url.decode("utf-8")
except (UnicodeDecodeError, AttributeError):
return False
try:
hostname = urlsplit(url).hostname
except (ValueError, TypeError, AttributeError):
return False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In urllib3, the url parameter passed to urlopen can be a urllib3.util.Url object (or other string-like/URL objects) rather than a plain str or bytes. Currently, passing a urllib3.util.Url object to is_mtls_endpoint will cause urlsplit(url) to raise a TypeError, which is caught and results in returning False—even if the object represents a valid mTLS endpoint.

To prevent this and ensure robust compatibility with urllib3's native URL objects, we should check if the input has a .url attribute (which urllib3.util.Url exposes as a property returning the string representation) or fall back to converting it to a string.

Suggested change
if not url:
return False
if isinstance(url, bytes):
try:
url = url.decode("utf-8")
except (UnicodeDecodeError, AttributeError):
return False
try:
hostname = urlsplit(url).hostname
except (ValueError, TypeError, AttributeError):
return False
if not url:
return False
if isinstance(url, bytes):
try:
url = url.decode("utf-8")
except (UnicodeDecodeError, AttributeError):
return False
elif not isinstance(url, str):
if hasattr(url, "url"):
url = url.url
else:
try:
url = str(url)
except Exception:
return False
try:
hostname = urlsplit(url).hostname
except (ValueError, TypeError, AttributeError):
return False
References
  1. Adheres to the defensive programming guidelines in Section 2 of the Repository Style Guide by validating and normalizing the input type before performing operations that could raise TypeErrors. (link)
  2. Do not replace historical graceful fallback behaviors (such as returning False/falling back to standard TLS) with exceptions if doing so would introduce breaking changes for downstream users and violate backwards compatibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Fix(auth): incorrect mTLS endpoint detection causes false positive cert rotations and breaks PSC endpoints

2 participants