Skip to content

[release/10.0] Reject ASCII control characters in cookie auth return URLs#67155

Open
github-actions[bot] wants to merge 2 commits into
release/10.0from
backport/pr-66876-to-release/10.0
Open

[release/10.0] Reject ASCII control characters in cookie auth return URLs#67155
github-actions[bot] wants to merge 2 commits into
release/10.0from
backport/pr-66876-to-release/10.0

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Backport of #66876 to release/10.0

/cc @rokonec

Reject ASCII control characters in cookie auth return URLs

Share SharedUrlHelper.IsLocalUrl so cookie auth rejects control chars in ReturnUrl.

Description

CookieAuthenticationHandler.IsHostRelative was missing the ASCII control-character guard that SharedUrlHelper.IsLocalUrl and MVC's UrlHelperBase.CheckIsLocalUrl already enforce. A ReturnUrl query value containing \r, \n, \t, \0, or \u007F flowed verbatim into the Location response header on the cookie auth LoginPath / LogoutPath redirect flow, enabling header-splitting / response-injection.

This change consolidates the three near-identical copies of the local-URL predicate onto the single SharedUrlHelper.IsLocalUrl implementation (net +11 / −104 across four files):

  • src/Shared/ResultsHelpers/SharedUrlHelper.cs// SECURITY: comment marking it the single source of truth (no IL change).
  • src/Mvc/Mvc.Core/src/Routing/UrlHelperBase.csCheckIsLocalUrl collapsed to a forwarder (behavior-preserving refactor).
  • src/Security/Authentication/Cookies/src/Microsoft.AspNetCore.Authentication.Cookies.csproj — links the shared SharedUrlHelper.cs.
  • src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.csIsHostRelative becomes non-empty + starts with / + SharedUrlHelper.IsLocalUrl(path); the explicit / check keeps rejecting ~/ application-relative paths.

Fixes #66806

Customer Impact

A cookie-authentication app that redirects to a user-supplied ReturnUrl (the default LoginPath / LogoutPath flow) is vulnerable to HTTP response header injection / response splitting. An attacker can craft a ReturnUrl containing CR/LF or other ASCII control characters (\r, \n, \t, \0, \u007F) that is written verbatim into the Location response header. The fix rejects these control characters, closing the gap and aligning cookie auth with the guard already enforced by MVC URL helpers and Results.LocalRedirect.

Regression?

  • Yes
  • No

Long-standing gap in CookieAuthenticationHandler.IsHostRelative; the control-character guard was never present in the cookie auth path. Not a regression from a specific release.

Risk

  • High
  • Medium
  • Low

Small, contained change that routes three copies of the same predicate through the already-shipping, already-tested SharedUrlHelper.IsLocalUrl. The Microsoft.AspNetCore.Mvc.Core edit is a behavior-preserving refactor (forwarder). The cookie auth path[0] == '/' guard preserves existing rejection of ~/ application-relative paths. No public API change. Covered by 35 new test rows plus the existing MVC / Results suites.

Verification

  • Manual (required)
  • Automated

35 new [Theory] rows in src/Security/Authentication/test/CookieTests.cs cover control-character rejection, benign return URLs still honored, and the non-host-relative branches. All affected projects build clean; the cookie auth fixture passes (117 passed / 0 failed / 1 pre-existing unrelated skip).

Packaging changes reviewed?

  • Yes
  • No
  • N/A

No packaging changes: no new package, no dependency or public-API change. The cookie auth .csproj only adds a shared-source <Compile> link.

rokonec added 2 commits June 11, 2026 17:25
CookieAuthenticationHandler.IsHostRelative now mirrors the
control-character guard from SharedUrlHelper.IsLocalUrl and
UrlHelperBase.CheckIsLocalUrl, blocking U+0000-U+001F and U+007F in
ReturnUrl query values to prevent Location header injection through
the LoginPath / LogoutPath redirect flow.

Adds 35 new theory rows in CookieTests covering control-character
rejection, benign honor cases, and broader non-host-relative rejection
(protocol-relative, "/\", "~/", absolute, relative, scheme confusion,
whitespace).

Fixes #66806
- Link SharedUrlHelper.cs into Cookies project and forward CookieAuthenticationHandler.IsHostRelative
- Forward UrlHelperBase.CheckIsLocalUrl to SharedUrlHelper.IsLocalUrl
- Add SECURITY note on SharedUrlHelper.IsLocalUrl flagging it as an open-redirect guard
@github-actions github-actions Bot requested review from a team and halter73 as code owners June 11, 2026 17:25
@rokonec rokonec added the Servicing-consider Shiproom approval is required for the issue label Jun 11, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hi @github-actions[bot]. Please make sure you've updated the PR description to use the Shiproom Template. Also, make sure this PR is not marked as a draft and is ready-to-merge.

To learn more about how to prepare a servicing PR click here.

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

Labels

area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer Servicing-consider Shiproom approval is required for the issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant