Skip to content

azure-core: redirect credential cleanup strips only Authorization; custom-header key credentials and SAS are sent to the redirect target #49786

Open

Description

@venkatchalla06

Summary

azure-core's cross-domain redirect credential cleanup only removes the Authorization header family. Credentials applied by AzureKeyCredentialPolicy (a custom-named header, e.g. api-key / Ocp-Apim-Subscription-Key) and AzureSasCredentialPolicy (a SAS appended to the URL query) are not removed, so on a cross-domain HTTP redirect they are transmitted to the redirect target host. Bearer tokens are correctly protected because their header is Authorization, which is stripped — that asymmetry is the defect.

This is a defense-in-depth / internal-consistency gap, not a demonstrated remote exploit: azure-core already treats a cross-domain redirect as a credential-trust boundary (RedirectPolicy sets insecure_domain_change and SensitiveHeaderCleanupPolicy exists specifically to strip sensitive headers on that event), but the protection is hardcoded to the Authorization family and silently misses the custom-header key credentials and SAS that are the default auth for a class of first-party data-plane SDKs. Filing here as a hardening improvement; the credential-forwarding class was reviewed by MSRC and considered below their security-servicing bar, which is why this is raised publicly as a consistency fix rather than through the security channel.

Root cause (verified on main @ 7c468236, azure-core 1.42.0-dev)

  • azure/core/pipeline/policies/_redirect.py:79 — REDIRECT_HEADERS_BLACKLIST = frozenset(["Authorization"]).
  • azure/core/pipeline/policies/_sensitive_header_cleanup_policy.py:46 — DEFAULT_SENSITIVE_HEADERS = {"Authorization", "x-ms-authorization-auxiliary"}; on_request pops only those when insecure_domain_change is set.
  • azure/core/pipeline/policies/_authentication.py:315 — AzureKeyCredentialPolicy.on_request sets headers[self._name] (custom name) on every send.
  • azure/core/pipeline/policies/_authentication.py:342-355 — AzureSasCredentialPolicy.on_request re-appends the SAS to the URL query on every send.

Pipeline order (shipped default, e.g. azure-search-documents, and _pipeline_client.py): redirect → retry → authentication → … → SensitiveHeaderCleanupPolicy → transport. On the redirected request the credential policy re-applies the credential; the cleanup policy removes only Authorization; the custom key header / SAS survives to the transport.

Default-on configurations

Each pairs AzureKeyCredentialPolicy (custom header) with a default-constructed RedirectPolicy, with no opt-in from the user:

  • azure-search-documents (api-key)
  • azure-ai-documentintelligence (Ocp-Apim-Subscription-Key)
  • azure-ai-contentsafety (Ocp-Apim-Subscription-Key)
  • azure-ai-formrecognizer

Reproduction (executed)

A default-configured azure.search.documents.SearchClient (AzureKeyCredential, no custom policies) pointed at a service that returns 302 Location: https://<other-authority>/… transmits its api-key header to the redirect-target host. Verified both with the real SearchClient and with the real azure-core policies assembled in the shipped order. (Note on scope: this demonstrates the policy-level credential leak; it does not demonstrate a production Azure service emitting such a cross-domain redirect — that prerequisite, e.g. a service open-redirect or on-path TLS, is not shown and is the main limitation of the real-world attack path.)

Expected behavior

On a cross-domain redirect the key-credential header and the SAS query signature should not be sent to the redirect target — matching the protection already applied to Authorization.

Cross-language note

Java azure-core (RedirectPolicy.java, clientcore HttpRedirectPolicy.java) and JS also strip only Authorization; Python is the directly default-on case.

Proposed fix

PR follows: have AzureKeyCredentialPolicy/AzureSasCredentialPolicy honor the same insecure_domain_change signal and withhold (and remove) their credential on a cross-domain redirect.

Activity

  1. added
    questionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that
    ClientThis issue points to a problem in the data-plane of the library.
    customer-reportedIssues that are reported by GitHub users external to the Azure organization.
    needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK team
    on Oct 31, 2026
  2. github-actions commented on Oct 31, 2026

    @github-actions
    Contributor

    Thank you for your feedback. Tagging and routing to the team member(s) best able to assist.

    Generated by Agentic Triage for #49786 · copilot · sonnet50 · 32.7 AIC · ⌖ 0.647 AIC · ⊞ 4.8K · ◷

  3. github-actions commented on Oct 31, 2026

    @github-actions
    Contributor

    🎯 Agentic Issue Triage

    Summary: azure-core's cross-domain redirect protection (SensitiveHeaderCleanupPolicy) only strips the Authorization/x-ms-authorization-auxiliary headers, so custom-named key-credential headers (e.g. api-key, Ocp-Apim-Subscription-Key) from AzureKeyCredentialPolicy, and SAS tokens appended to the URL query by AzureSasCredentialPolicy, are still re-applied and sent to a redirect target on a cross-domain insecure_domain_change redirect.

    📋 Issue Details

    Package: azure-core (1.42.0-dev, verified on main @ 7c468236)
    Affected API: azure.core.pipeline.policies._redirect.RedirectPolicy (REDIRECT_HEADERS_BLACKLIST), _sensitive_header_cleanup_policy.SensitiveHeaderCleanupPolicy (DEFAULT_SENSITIVE_HEADERS), _authentication.AzureKeyCredentialPolicy, _authentication.AzureSasCredentialPolicy
    Scenarios:

    • A default-configured SearchClient (azure-search-documents, using AzureKeyCredential) is redirected cross-domain (302) and its api-key header is sent to the new host.
    • Similar exposure affects azure-ai-documentintelligence, azure-ai-contentsafety, azure-ai-formrecognizer (all use Ocp-Apim-Subscription-Key), and any AzureSasCredentialPolicy consumer, since the SAS is reappended to the query string on every send regardless of domain change.

    Root ask: Extend the same cross-domain credential-stripping protection applied to Authorization so that custom key-credential headers and SAS query signatures are also withheld/removed on an insecure_domain_change redirect.

    🔎 Debugging / Reproduction Notes

    Reporter already did root-cause analysis with specific file/line references and reproduced the leak using the real SearchClient and the shipped pipeline policy order (redirect → retry → authentication → ... → SensitiveHeaderCleanupPolicy → transport). A fix PR (#49787) has already been opened by the reporter, closing this issue once merged.

    Suggested investigation steps:

    1. Confirm whether AzureKeyCredentialPolicy/AzureSasCredentialPolicy can observe the insecure_domain_change pipeline context flag the same way SensitiveHeaderCleanupPolicy does.
    2. Review PR [azure-core] Withhold key/SAS credentials on cross-domain redirect #49787 for correctness, cross-language consistency (Java/JS have the same gap per reporter), and regression test coverage.
    3. Verify no existing legitimate same-domain redirect scenarios are broken by withholding the header/SAS.
    🏷️ Label Confidence
    • Category: Client — the issue is about data-plane SDK pipeline policy behavior (not a azure-mgmt-* package).
    • Service: Azure.Core — issue explicitly names azure-core source files and policies.
    • Confidence: High — the issue unambiguously references azure-core file paths and the affected policies with no competing service.
    👥 Owner Routing
    • Matched CODEOWNERS entry: # ServiceLabel: %Azure.Core (line 19) — matched directly on the predicted service label during bottom-to-top scan; the %Core.Http entry above it (line 16) was skipped as it is a different, unrelated label.
    • AzureSdkOwners: @kashifkhan
    • ServiceOwners: none listed
    • Routing action: Assigned @kashifkhan (sole AzureSdkOwner); added needs-team-attention since this is customer-reported.
    • Scan notes: No other Azure.Core entries exist further down the file; this was the only and first match encountered scanning upward.

    Generated by Agentic Triage for #49786 · copilot · sonnet50 · 32.7 AIC · ⌖ 0.647 AIC · ⊞ 4.8K · ◷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Azure.CoreClientThis issue points to a problem in the data-plane of the library.customer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamquestionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions