Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package azure-cli-core for openSUSE:Factory checked in at 2026-07-08 17:38:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/azure-cli-core (Old) and /work/SRC/openSUSE:Factory/.azure-cli-core.new.1982 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "azure-cli-core" Wed Jul 8 17:38:07 2026 rev:97 rq:1364354 version:2.88.0 Changes: -------- --- /work/SRC/openSUSE:Factory/azure-cli-core/azure-cli-core.changes 2026-06-08 14:24:05.754011336 +0200 +++ /work/SRC/openSUSE:Factory/.azure-cli-core.new.1982/azure-cli-core.changes 2026-07-08 17:41:09.555134241 +0200 @@ -1,0 +2,9 @@ +Tue Jul 7 12:47:24 UTC 2026 - John Paul Adrian Glaubitz <[email protected]> + +- New upstream release + + Version 2.88.0 + + For detailed information about changes see the + HISTORY.rst file provided with this package +- Update Requires from setup.py + +------------------------------------------------------------------- Old: ---- azure_cli_core-2.87.0.tar.gz New: ---- azure_cli_core-2.88.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ azure-cli-core.spec ++++++ --- /var/tmp/diff_new_pack.lCLyTB/_old 2026-07-08 17:41:10.839178985 +0200 +++ /var/tmp/diff_new_pack.lCLyTB/_new 2026-07-08 17:41:10.839178985 +0200 @@ -24,7 +24,7 @@ %global _sitelibdir %{%{pythons}_sitelib} Name: azure-cli-core -Version: 2.87.0 +Version: 2.88.0 Release: 0 Summary: Microsoft Azure CLI Core Module License: MIT @@ -59,7 +59,7 @@ Requires: %{pythons}-msal-extensions >= 1.3.1 Requires: %{pythons}-packaging >= 20.9 Requires: %{pythons}-pip -Requires: %{pythons}-pkginfo >= 1.5.0.1 +Requires: %{pythons}-pkginfo >= 1.12.0 Requires: %{pythons}-psutil >= 5.9 Requires: %{pythons}-py-deviceid Requires: %{pythons}-pyOpenSSL >= 17.1.0 ++++++ azure_cli_core-2.87.0.tar.gz -> azure_cli_core-2.88.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/HISTORY.rst new/azure_cli_core-2.88.0/HISTORY.rst --- old/azure_cli_core-2.87.0/HISTORY.rst 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/HISTORY.rst 2026-06-30 13:01:58.000000000 +0200 @@ -3,6 +3,11 @@ Release History =============== +2.88.0 +++++++ +* Resolve CVE-2026-48526 (#33562) +* Update global policy argument `--acquire-policy-token` to pick up new api-version and propagate correlation-id (#33661) + 2.87.0 ++++++ * Resolve CVE-2026-44431 (#33351) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/PKG-INFO new/azure_cli_core-2.88.0/PKG-INFO --- old/azure_cli_core-2.87.0/PKG-INFO 2026-05-26 08:39:29.832620900 +0200 +++ new/azure_cli_core-2.88.0/PKG-INFO 2026-06-30 13:02:37.228244300 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: azure-cli-core -Version: 2.87.0 +Version: 2.88.0 Summary: Microsoft Azure Command-Line Tools Core Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation @@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.10.0 License-File: LICENSE.txt @@ -32,7 +33,7 @@ Requires-Dist: msal[broker]==1.36.0; sys_platform == "win32" Requires-Dist: msal==1.36.0; sys_platform != "win32" Requires-Dist: packaging>=20.9 -Requires-Dist: pkginfo>=1.5.0.1 +Requires-Dist: pkginfo>=1.12.0 Requires-Dist: psutil>=5.9; sys_platform != "cygwin" Requires-Dist: PyJWT>=2.1.0 Requires-Dist: pyopenssl>=17.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/__init__.py new/azure_cli_core-2.88.0/azure/cli/core/__init__.py --- old/azure_cli_core-2.87.0/azure/cli/core/__init__.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/__init__.py 2026-06-30 13:01:58.000000000 +0200 @@ -4,7 +4,7 @@ # -------------------------------------------------------------------------------------------- # pylint: disable=line-too-long -__version__ = "2.87.0" +__version__ = "2.88.0" import os import sys @@ -37,10 +37,6 @@ ALWAYS_LOADED_MODULES = [] # Extensions that will always be loaded if installed. They don't expose commands but hook into CLI core. ALWAYS_LOADED_EXTENSIONS = ['azext_ai_examples', 'azext_next'] -# Timeout (in seconds) for loading a single module. Acts as a safety valve to prevent indefinite hangs -MODULE_LOAD_TIMEOUT_SECONDS = 60 -# Maximum number of worker threads for parallel module loading. -MAX_WORKER_THREAD_COUNT = 4 def _get_top_level_command(args): @@ -322,6 +318,7 @@ start_time = time.perf_counter() logger.debug("Loading command modules...") + logger.debug(self.header_mod) results = self._load_modules(args, command_modules) count, cumulative_group_count, cumulative_command_count = \ @@ -664,42 +661,14 @@ loader._update_command_definitions() # pylint: disable=protected-access def _load_modules(self, args, command_modules): - """Load command modules using ThreadPoolExecutor with timeout protection.""" - import concurrent.futures - from concurrent.futures import ThreadPoolExecutor + """Load command modules sequentially.""" from azure.cli.core.commands import BLOCKED_MODS results = [] - with ThreadPoolExecutor(max_workers=MAX_WORKER_THREAD_COUNT) as executor: - future_to_module = {executor.submit(self._load_single_module, mod, args): mod - for mod in command_modules if mod not in BLOCKED_MODS} - - try: - for future in concurrent.futures.as_completed(future_to_module, timeout=MODULE_LOAD_TIMEOUT_SECONDS): - try: - result = future.result() - results.append(result) - except (ImportError, AttributeError, TypeError, ValueError) as ex: - mod = future_to_module[future] - logger.warning("Module '%s' load failed: %s", mod, ex) - results.append(ModuleLoadResult(mod, {}, {}, 0, ex)) - except Exception as ex: # pylint: disable=broad-exception-caught - mod = future_to_module[future] - logger.warning("Module '%s' load failed with unexpected exception: %s", mod, ex) - results.append(ModuleLoadResult(mod, {}, {}, 0, ex)) - except concurrent.futures.TimeoutError: - for future, mod in future_to_module.items(): - if future.done(): - try: - result = future.result() - results.append(result) - except Exception as ex: # pylint: disable=broad-exception-caught - logger.warning("Module '%s' load failed: %s", mod, ex) - results.append(ModuleLoadResult(mod, {}, {}, 0, ex)) - else: - logger.warning("Module '%s' load timeout after %s seconds", mod, MODULE_LOAD_TIMEOUT_SECONDS) - results.append(ModuleLoadResult(mod, {}, {}, 0, - Exception(f"Module '{mod}' load timeout"))) + for mod in command_modules: + if mod in BLOCKED_MODS: + continue + results.append(self._load_single_module(mod, args)) return results @@ -712,6 +681,8 @@ module_command_table, module_group_table, command_loader = _load_module_command_loader(self, args, mod) import_module_breaking_changes(mod) elapsed_time = time.perf_counter() - start_time + logger.debug(self.item_format_string, mod, elapsed_time, + len(module_group_table), len(module_command_table)) return ModuleLoadResult(mod, module_command_table, module_group_table, elapsed_time, command_loader=command_loader) except Exception as ex: # pylint: disable=broad-except tb_str = traceback.format_exc() @@ -744,13 +715,9 @@ self.command_table.update(result.command_table) self.command_group_table.update(result.group_table) - logger.debug(self.item_format_string, result.module_name, result.elapsed_time, - len(result.group_table), len(result.command_table)) - def _process_results_with_timing(self, results): """Process pre-loaded module results with timing and progress reporting.""" - logger.debug("Loaded command modules in parallel:") - logger.debug(self.header_mod) + logger.debug("Loaded command modules:") count = 0 cumulative_group_count = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/_profile.py new/azure_cli_core-2.88.0/azure/cli/core/_profile.py --- old/azure_cli_core-2.87.0/azure/cli/core/_profile.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/_profile.py 2026-06-30 13:01:58.000000000 +0200 @@ -441,6 +441,11 @@ def get_msal_token(self, scopes, data): """Get VM SSH certificate. DO NOT use it for other purposes. To get an access token, use get_raw_token instead. """ + account = self.get_subscription() + managed_identity_type, _ = Profile._parse_managed_identity_account(account) + if managed_identity_type or (in_cloud_console() and account[_USER_ENTITY].get(_CLOUD_SHELL_ID)): + raise AuthenticationError("VM SSH currently doesn't support managed identity or Cloud Shell.") + credential, _, _ = self.get_login_credentials(sdk_credential=False) from .auth.constants import ACCESS_TOKEN certificate_string = credential.acquire_token(scopes, data=data)[ACCESS_TOKEN] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/aaz/_arg_fmt.py new/azure_cli_core-2.88.0/azure/cli/core/aaz/_arg_fmt.py --- old/azure_cli_core-2.87.0/azure/cli/core/aaz/_arg_fmt.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/aaz/_arg_fmt.py 2026-06-30 13:01:58.000000000 +0200 @@ -760,10 +760,19 @@ raise AAZInvalidArgValueError("Decoded object is not a dictionary.") try: - _, _ = obj["next_link"], obj["offset"] + next_link, _ = obj["next_link"], obj["offset"] except KeyError: raise AAZInvalidArgValueError("`next_link` or `offset` doesn't exist.") + # `next_link` is a URL that the next page request is sent to with an Azure access token. + # Validate it shares the same origin as a trusted endpoint of the active cloud to prevent + # the token from being sent to an attacker-controlled host such as + # `https://management.azure.com.attacker`. + if next_link is not None: + from azure.cli.core.util import is_trusted_cloud_endpoint + if not is_trusted_cloud_endpoint(next_link, ctx.cli_ctx): + raise AAZInvalidArgValueError("`next_link` '{}' is not a valid endpoint.".format(next_link)) + assert isinstance(value, AAZSimpleValue) data = value._data if data == AAZUndefined or data is None or value._is_patch: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/commandIndex.latest.json new/azure_cli_core-2.88.0/azure/cli/core/commandIndex.latest.json --- old/azure_cli_core-2.87.0/azure/cli/core/commandIndex.latest.json 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/commandIndex.latest.json 2026-06-30 13:01:58.000000000 +0200 @@ -1,5 +1,5 @@ { - "version": "2.87.0", + "version": "2.88.0", "cloudProfile": "latest", "commandIndex": { "account": [ @@ -15,9 +15,6 @@ "advisor": [ "azure.cli.command_modules.advisor" ], - "afd": [ - "azure.cli.command_modules.cdn" - ], "aks": [ "azure.cli.command_modules.acs", "azure.cli.command_modules.serviceconnector" @@ -61,9 +58,6 @@ "capacity": [ "azure.cli.command_modules.vm" ], - "cdn": [ - "azure.cli.command_modules.cdn" - ], "cloud": [ "azure.cli.command_modules.cloud" ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/commands/arm.py new/azure_cli_core-2.88.0/azure/cli/core/commands/arm.py --- old/azure_cli_core-2.87.0/azure/cli/core/commands/arm.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/commands/arm.py 2026-06-30 13:01:58.000000000 +0200 @@ -774,6 +774,11 @@ import time from azure.core.exceptions import HttpResponseError + # Coerce AAZSimpleValue/model values to plain strings for SDK 5.0.0b2 compatibility + principal_id = str(principal_id) if principal_id else principal_id + identity_role = str(identity_role) if identity_role else identity_role + identity_scope = str(identity_scope) if identity_scope else identity_scope + identity_role_id = resolve_role_id(cli_ctx, identity_role, identity_scope) assignments_client = get_mgmt_service_client(cli_ctx, ResourceType.MGMT_AUTHORIZATION).role_assignments RoleAssignmentCreateParameters = get_sdk(cli_ctx, ResourceType.MGMT_AUTHORIZATION, @@ -818,7 +823,7 @@ except ValueError: pass if not role_id: # retrieve role id - role_defs = list(client.list(scope, "roleName eq '{}'".format(role))) + role_defs = list(client.list(scope, filter="roleName eq '{}'".format(role))) if not role_defs: raise CLIError("Role '{}' doesn't exist.".format(role)) if len(role_defs) > 1: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/helpIndex.latest.json new/azure_cli_core-2.88.0/azure/cli/core/helpIndex.latest.json --- old/azure_cli_core-2.87.0/azure/cli/core/helpIndex.latest.json 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/helpIndex.latest.json 2026-06-30 13:01:58.000000000 +0200 @@ -1,5 +1,5 @@ { - "version": "2.87.0", + "version": "2.88.0", "cloudProfile": "latest", "helpIndex": { "groups": { @@ -19,10 +19,6 @@ "summary": "Manage Azure Advisor.", "tags": "" }, - "afd": { - "summary": "Manage Azure Front Door Standard/Premium.", - "tags": "" - }, "aks": { "summary": "Azure Kubernetes Service.", "tags": "" @@ -75,10 +71,6 @@ "summary": "Manage capacity.", "tags": "" }, - "cdn": { - "summary": "Manage Azure Content Delivery Networks (CDNs).", - "tags": "" - }, "cloud": { "summary": "Manage registered Azure clouds.", "tags": "" @@ -89,7 +81,7 @@ }, "compute-fleet": { "summary": "Manage for Azure Compute Fleet.", - "tags": "[Preview]" + "tags": "" }, "compute-recommender": { "summary": "Manage sku/zone/region recommender info for compute resources.", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/profiles/_shared.py new/azure_cli_core-2.88.0/azure/cli/core/profiles/_shared.py --- old/azure_cli_core-2.87.0/azure/cli/core/profiles/_shared.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/profiles/_shared.py 2026-06-30 13:01:58.000000000 +0200 @@ -97,7 +97,6 @@ MGMT_BATCHAI = ('azure.mgmt.batchai', None) MGMT_BILLING = ('azure.mgmt.billing', None) MGMT_BOTSERVICE = ('azure.mgmt.botservice', None) - MGMT_CDN = ('azure.mgmt.cdn', None) MGMT_COGNITIVESERVICES = ('azure.mgmt.cognitiveservices', None) MGMT_CONTAINERINSTANCE = ('azure.mgmt.containerinstance', None) MGMT_COSMOSDB = ('azure.mgmt.cosmosdb', None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/sdk/policies.py new/azure_cli_core-2.88.0/azure/cli/core/sdk/policies.py --- old/azure_cli_core-2.87.0/azure/cli/core/sdk/policies.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/sdk/policies.py 2026-06-30 13:01:58.000000000 +0200 @@ -6,6 +6,7 @@ import logging import re import types +import uuid from azure.core.pipeline.policies import SansIOHTTPPolicy, UserAgentPolicy from knack.log import get_logger @@ -111,7 +112,7 @@ http_request = request.http_request if getattr(http_request, 'method', '') == 'GET': return - ACQUIRE_POLICY_TOKEN_URL = '/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/acquirePolicyToken?api-version=2025-03-01' + ACQUIRE_POLICY_TOKEN_URL = '/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/acquirePolicyToken?api-version=2025-11-01' policy_token = None from azure.cli.core.azclierror import ServiceError @@ -135,10 +136,18 @@ }, "changeReference": cli_ctx.data.get('_change_reference', None) } + + # Reuse the original request's x-ms-correlation-request-id so the acquirePolicyToken call shares the same correlation ID as the operation it is gating. + headers = ['Content-Type=application/json', 'x-ms-force-sync=true'] + correlation_id = http_request.headers.get('x-ms-correlation-request-id') + if not correlation_id: + correlation_id = str(uuid.uuid4()) + http_request.headers['x-ms-correlation-request-id'] = correlation_id + headers.append('x-ms-correlation-request-id={}'.format(correlation_id)) + acquire_policy_token_response = send_raw_request(cli_ctx, 'POST', ACQUIRE_POLICY_TOKEN_URL, - headers=['Content-Type=application/json', - 'x-ms-force-sync=true'], + headers=headers, body=json.dumps(acquire_policy_token_body)) if acquire_policy_token_response.status_code == 200 and acquire_policy_token_response.content: response_content = json.loads(acquire_policy_token_response.content) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure/cli/core/util.py new/azure_cli_core-2.88.0/azure/cli/core/util.py --- old/azure_cli_core-2.87.0/azure/cli/core/util.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure/cli/core/util.py 2026-06-30 13:01:58.000000000 +0200 @@ -1041,21 +1041,13 @@ if not skip_authorization_header and url.lower().startswith('https://'): # Prepare `resource` for `get_raw_token` if not resource: - # If url starts with ARM endpoint, like `https://management.azure.com/`, + # If url's origin matches the ARM endpoint, like `https://management.azure.com/`, # use `active_directory_resource_id` for resource, like `https://management.core.windows.net/`. # This follows the same behavior as `azure.cli.core.commands.client_factory._get_mgmt_service_client` - if url.lower().startswith(endpoints.resource_manager.rstrip('/')): + if is_same_origin(url, endpoints.resource_manager): resource = endpoints.active_directory_resource_id else: - from azure.cli.core.cloud import CloudEndpointNotSetException - for p in [x for x in dir(endpoints) if not x.startswith('_')]: - try: - value = getattr(endpoints, p) - except CloudEndpointNotSetException: - continue - if isinstance(value, str) and url.lower().startswith(value.lower()): - resource = value - break + resource = match_cloud_endpoint(url, cli_ctx) if resource: # Prepare `subscription` for `get_raw_token` # If this is an ARM request, try to extract subscription ID from the URL. @@ -1063,7 +1055,7 @@ # TODO: In the future when multi-tenant subscription is supported, we won't be able to uniquely identify # the token from subscription anymore. token_subscription = None - if url.lower().startswith(endpoints.resource_manager.rstrip('/')): + if is_same_origin(url, endpoints.resource_manager): token_subscription = _extract_subscription_id(url) if token_subscription: logger.debug('Retrieving token for resource %s, subscription %s', resource, token_subscription) @@ -1210,6 +1202,92 @@ return req.read() +def is_same_origin(url, endpoint): + """Check whether ``url`` and ``endpoint`` share the same origin (scheme + host + port). + + This performs an exact origin comparison rather than substring or prefix matching, so a + malicious host such as ``https://management.azure.com.attacker`` is not mistaken for + the trusted endpoint ``https://management.azure.com``. It is intended for validating that a + URL points to a trusted endpoint before sensitive data (e.g., an Azure access token) is sent + to it. + + :param url: The URL to validate, e.g., ``https://management.azure.com/subscriptions/...``. + :param endpoint: The trusted endpoint to validate against, e.g., ``https://management.azure.com/``. + :return: ``True`` if both share the same origin, otherwise ``False``. + :rtype: bool + """ + from urllib.parse import urlparse + + if not isinstance(url, str) or not isinstance(endpoint, str): + return False + + try: + url_parts = urlparse(url) + endpoint_parts = urlparse(endpoint) + + except (TypeError, ValueError): + return False + + # Require a real host on both sides to avoid false positives against non-URL endpoint values. + # `hostname` (rather than `netloc`) is used so that userinfo tricks like + # `https://management.azure.com@attacker` resolve to the actual host `attacker`. + if not url_parts.hostname or not endpoint_parts.hostname: + return False + + def _effective_port(parts): + # Treat a missing port as the scheme's default port so that, e.g., + # `https://management.azure.com:443/` and `https://management.azure.com/` are equivalent. + if parts.port is not None: + return parts.port + + return {'http': 80, 'https': 443}.get(parts.scheme.lower()) + + try: + if _effective_port(url_parts) != _effective_port(endpoint_parts): + return False + + except ValueError: + return False + + return (url_parts.scheme.lower() == endpoint_parts.scheme.lower() and + url_parts.hostname.lower() == endpoint_parts.hostname.lower()) + + +def match_cloud_endpoint(url, cli_ctx): + """Return the active cloud endpoint that shares the same origin as ``url``. + + :param url: The URL to match, e.g., ``https://management.azure.com/subscriptions/...``. + :param cli_ctx: The CLI context whose active cloud's endpoints are treated as trusted. + :return: The matching endpoint value, or ``None`` if no endpoint shares ``url``'s origin. + :rtype: str or None + """ + from azure.cli.core.cloud import CloudEndpointNotSetException + + endpoints = cli_ctx.cloud.endpoints + for p in [x for x in dir(endpoints) if not x.startswith('_')]: + try: + value = getattr(endpoints, p) + + except CloudEndpointNotSetException: + continue + + if isinstance(value, str) and is_same_origin(url, value): + return value + + return None + + +def is_trusted_cloud_endpoint(url, cli_ctx): + """Check whether ``url`` shares the same origin as any endpoint of the active cloud. + + :param url: The URL to validate, e.g., ``https://management.azure.com/subscriptions/...``. + :param cli_ctx: The CLI context whose active cloud's endpoints are treated as trusted. + :return: ``True`` if ``url`` shares the same origin as any cloud endpoint, otherwise ``False``. + :rtype: bool + """ + return match_cloud_endpoint(url, cli_ctx) is not None + + def parse_proxy_resource_id(rid): """Parses a resource_id into its various parts. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure_cli_core.egg-info/PKG-INFO new/azure_cli_core-2.88.0/azure_cli_core.egg-info/PKG-INFO --- old/azure_cli_core-2.87.0/azure_cli_core.egg-info/PKG-INFO 2026-05-26 08:39:29.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure_cli_core.egg-info/PKG-INFO 2026-06-30 13:02:37.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: azure-cli-core -Version: 2.87.0 +Version: 2.88.0 Summary: Microsoft Azure Command-Line Tools Core Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation @@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.10.0 License-File: LICENSE.txt @@ -32,7 +33,7 @@ Requires-Dist: msal[broker]==1.36.0; sys_platform == "win32" Requires-Dist: msal==1.36.0; sys_platform != "win32" Requires-Dist: packaging>=20.9 -Requires-Dist: pkginfo>=1.5.0.1 +Requires-Dist: pkginfo>=1.12.0 Requires-Dist: psutil>=5.9; sys_platform != "cygwin" Requires-Dist: PyJWT>=2.1.0 Requires-Dist: pyopenssl>=17.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/azure_cli_core.egg-info/requires.txt new/azure_cli_core-2.88.0/azure_cli_core.egg-info/requires.txt --- old/azure_cli_core-2.87.0/azure_cli_core.egg-info/requires.txt 2026-05-26 08:39:29.000000000 +0200 +++ new/azure_cli_core-2.88.0/azure_cli_core.egg-info/requires.txt 2026-06-30 13:02:37.000000000 +0200 @@ -9,7 +9,7 @@ microsoft-security-utilities-secret-masker~=1.0.0b4 msal-extensions==1.3.1 packaging>=20.9 -pkginfo>=1.5.0.1 +pkginfo>=1.12.0 PyJWT>=2.1.0 pyopenssl>=17.1.0 py-deviceid diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure_cli_core-2.87.0/setup.py new/azure_cli_core-2.88.0/setup.py --- old/azure_cli_core-2.87.0/setup.py 2026-05-26 08:38:40.000000000 +0200 +++ new/azure_cli_core-2.88.0/setup.py 2026-06-30 13:01:58.000000000 +0200 @@ -8,7 +8,7 @@ from codecs import open from setuptools import setup, find_packages -VERSION = "2.87.0" +VERSION = "2.88.0" # If we have source, validate that our version numbers match # This should prevent uploading releases with mismatched versions. @@ -39,6 +39,7 @@ 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'License :: OSI Approved :: MIT License', ] @@ -58,7 +59,10 @@ 'msal[broker]==1.36.0; sys_platform == "win32"', 'msal==1.36.0; sys_platform != "win32"', 'packaging>=20.9', - 'pkginfo>=1.5.0.1', + # pkginfo>=1.12.0 reads the spec-defined wheel METADATA / unpacked .dist-info + # layout produced by modern wheel/setuptools (no metadata.json). Required so + # WheelExtension.get_metadata works without the legacy wheel==0.30.0 artifact. + 'pkginfo>=1.12.0', # psutil can't install on cygwin: https://github.com/Azure/azure-cli/issues/9399 'psutil>=5.9; sys_platform != "cygwin"', 'PyJWT>=2.1.0',
