Conversation
Improve readability of `ProxyingOpenApiDocument` logic. Update OpenAPI document writing method to handle JSON serialization asynchronously and add inline comments for future compatibility issues with OpenAPI library and .NET 10.
| @@ -0,0 +1 @@ | |||
| window.location.href = document.querySelector("meta[http-equiv=refresh]").getAttribute("data-url"); | |||
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
In general, the problem is that an attribute value from the DOM is treated as a fully trusted URL and used to navigate without any validation or encoding. To fix this safely without changing overall behavior, we should: (1) read the data-url attribute into a variable, (2) validate/normalize it using the URL constructor, (3) restrict acceptable schemes (e.g., only http: and https:), and optionally (4) prevent open redirects by allowing only same-origin URLs or a known set of domains. If validation fails, we should avoid navigating.
Specifically for BFF/v4/TokenExchange/TokenExchange.IdentityServer/wwwroot/js/signin-redirect.js, we can replace the one-liner with a small block:
- Retrieve the element via
document.querySelector("meta[http-equiv=refresh]"). - Get the
data-urlattribute into a local variable. - If no element or attribute is present, do nothing.
- Construct a
URLobject with the value andwindow.location.originas base, so we handle relative URLs safely. - Check that the resulting URL’s protocol is
http:orhttps:(and optionally that its origin matcheswindow.location.originto avoid leaving the site). - Only then assign
window.location.href = url.toString();.
No external libraries are needed; URL is a standard web API. Changes are localized to the shown file and only expand the existing logic.
| @@ -1 +1,24 @@ | ||
| window.location.href = document.querySelector("meta[http-equiv=refresh]").getAttribute("data-url"); | ||
| (function () { | ||
| var metaRefresh = document.querySelector("meta[http-equiv=refresh]"); | ||
| if (!metaRefresh) { | ||
| return; | ||
| } | ||
|
|
||
| var dataUrl = metaRefresh.getAttribute("data-url"); | ||
| if (!dataUrl) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| // Resolve relative URLs against the current origin | ||
| var targetUrl = new URL(dataUrl, window.location.origin); | ||
|
|
||
| // Allow only HTTP(S) and same-origin navigation | ||
| if ((targetUrl.protocol === "http:" || targetUrl.protocol === "https:") && | ||
| targetUrl.origin === window.location.origin) { | ||
| window.location.href = targetUrl.toString(); | ||
| } | ||
| } catch (e) { | ||
| // Invalid URL; do not redirect | ||
| } | ||
| })(); |
| } | ||
|
|
||
| // If the URL is valid (for web), perform the redirect | ||
| window.location.href = url; |
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 days ago
In general, the fix is to stop treating arbitrary DOM-derived text as a fully trusted navigation target and to validate or constrain it before assigning it to window.location.href. Since the current script is for a “signin redirect,” it is typically sufficient (and safer) to only allow redirects within the same origin or to relative URLs generated by the server. This avoids interpreting attacker-controlled, absolute external URLs and keeps the redirect strictly within the application’s control.
The best minimal change, without altering overall behavior more than necessary, is:
- Keep the existing scheme validation for defense in depth.
- Additionally restrict the redirect so that:
- Relative URLs (starting with
/,./, or../) are allowed. - Absolute URLs are only allowed if their origin matches
window.location.origin.
- Relative URLs (starting with
- Use the
URLconstructor to safely parse absolute URLs, catching any invalid ones, and only then redirect.
This approach continues to support the intended redirect functionality for legitimate values while preventing the use of arbitrary, attacker-controlled URLs as redirect targets. All changes are confined to BFF/v4/docker/ContainerizedIdentityServer/wwwroot/js/signin-redirect.js, around the logic that validates and uses url (currently lines 19–29). No new imports are needed; we rely on standard browser URL and window.location APIs.
| @@ -16,15 +16,27 @@ | ||
| return; | ||
| } | ||
|
|
||
| // *** Protocol Validation (https://codeql.github.com/codeql-query-help/javascript/js-xss-through-dom/) *** | ||
| // Ensure the URL starts with http: or https: to prevent potential XSS via javascript: URIs | ||
| // *** URL Validation (https://codeql.github.com/codeql-query-help/javascript/js-xss-through-dom/) *** | ||
| // First, ensure that any absolute URL starts with http: or https: to prevent javascript:, data:, etc. | ||
| // Convert to lowercase for case-insensitive comparison. | ||
| var lowerUrl = url.toLowerCase(); | ||
| if (!lowerUrl.startsWith("http:") && !lowerUrl.startsWith("https:")) { | ||
| if (lowerUrl.indexOf(":") !== -1 && !lowerUrl.startsWith("http:") && !lowerUrl.startsWith("https:")) { | ||
| console.error("Signin redirect URL has an invalid scheme:", url); | ||
| return; | ||
| } | ||
|
|
||
| // If the URL is valid (for web), perform the redirect | ||
| window.location.href = url; | ||
| // Next, enforce that the redirect stays on the same origin or uses a relative URL. | ||
| try { | ||
| var targetUrl = new URL(url, window.location.href); | ||
| if (targetUrl.origin !== window.location.origin) { | ||
| console.error("Signin redirect URL has an invalid origin:", url); | ||
| return; | ||
| } | ||
| } catch (e) { | ||
| console.error("Signin redirect URL is not a valid URL:", url); | ||
| return; | ||
| } | ||
|
|
||
| // If the URL is valid and same-origin, perform the redirect. | ||
| window.location.href = targetUrl.href; | ||
| })(); |
Update Docker sample to .NET 10 and BFF v4