Fix open-redirect token leak and related auth hardening
Security review fixes: - Constrain OAuth connect returnUrl to a site-relative path so the redeemable token_key can't be redirected off-domain (was a refresh- token leak / connection hijack) - Route all login redirects (entra/dev/local) through ToLocalReturnUrl, also closing a protocol-relative // open redirect in local-login - Neutralize CSV formula prefixes in both audit-log exporters via CsvSanitizer - Force Secure flag on the prod auth cookie (Always, not SameAsRequest) - Gate admin pages with an app_role-claim "Admin" policy instead of a render-time check Findings and rationale recorded in SECURITY-TODO.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,4 +4,18 @@ public static class StringExtensions
|
||||
{
|
||||
public static string? TrimOrNull(this string? s)
|
||||
=> string.IsNullOrWhiteSpace(s) ? null : s.Trim();
|
||||
|
||||
/// <summary>
|
||||
/// Returns <paramref name="returnUrl"/> only when it is a safe site-relative path,
|
||||
/// otherwise "/". Rejects absolute URLs and protocol-relative paths ("//evil.com",
|
||||
/// "/\evil.com") so a post-auth / post-connect redirect can never leave the app.
|
||||
/// Used by every login and OAuth-connect redirect to prevent open redirects.
|
||||
/// </summary>
|
||||
public static string ToLocalReturnUrl(this string? returnUrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(returnUrl)) return "/";
|
||||
if (returnUrl[0] != '/') return "/"; // not site-relative
|
||||
if (returnUrl.Length > 1 && (returnUrl[1] == '/' || returnUrl[1] == '\\')) return "/"; // protocol-relative
|
||||
return returnUrl;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user