Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/components/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@labkey/components",
"version": "7.42.2",
"version": "7.42.3-fb-redirectGH1023.2",
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
"sideEffects": false,
"files": [
Expand Down
4 changes: 4 additions & 0 deletions packages/components/releaseNotes/components.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# @labkey/components
Components, models, actions, and utility functions for LabKey applications and pages

### version TBD
*Released*: TBD
- GitHub Issue #1023: Add redirect() helper that uses core-safeRedirect

### version 7.42.2
*Released*: 22 June 2026
- Styling update for user comment on large storage modal
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { enableMapSet, enablePatches } from 'immer';
import { applyURL, AppURL, buildURL, spliceURL } from './internal/url/AppURL';
import { AppLink } from './internal/url/AppLink';
import { useAppNavigate } from './internal/url/useAppNavigate';
import { hasParameter, imageURL, toggleParameter } from './internal/url/ActionURL';
import { hasParameter, imageURL, redirect, toggleParameter } from './internal/url/ActionURL';
import { getIntegerSearchParam } from './internal/url/utils';
import { Container } from './internal/components/base/models/Container';
import { hasAllPermissions, hasAnyPermissions, hasPermissions, User } from './internal/components/base/models/User';
Expand Down Expand Up @@ -1613,6 +1613,7 @@ export {
QuerySort,
quoteValueWithDelimiters,
RANGE_URIS,
redirect,
registerDefaultURLMappers,
registerFilterType,
registerInputRenderer,
Expand Down
5 changes: 5 additions & 0 deletions packages/components/src/internal/url/ActionURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,8 @@ export function imageURL(iconDir: string, src: string): string {
export function toggleParameter(parameterName: string, value: any): void {
setParameter(parameterName, hasParameter(parameterName) ? undefined : value);
}

// GitHub Issue #1023: Use the safeRedirect action to verify returnURL goes to local URLs only
export function redirect(url: string): void {
window.location.href = ActionURL.buildURL('core', 'safeRedirect', undefined, { returnUrl: url });
}
9 changes: 5 additions & 4 deletions packages/components/src/internal/url/useAppNavigate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { useNavigate } from 'react-router-dom';
import { useCallback, useMemo } from 'react';

import { redirect } from './ActionURL';
import { AppURL } from './AppURL';
import { parseAppPath } from './AppLink';

Expand All @@ -16,9 +17,9 @@ export type NavigateFn = (url: string | AppURL, replace?: boolean) => void;
* - If url is an AppURL it navigates via React Router's navigate method
* - If url is a string prefixed with # it will assume the URL is an app path, and use RR's navigate method
* - If url is a string pointing to an app path for the current app it will navigate via RR's navigate method
* - In all other cases it will use window.location.href to navigate to the given URL
* string it navigates via window.location.href = url. If you have an AppURL you should always pass it, instead of
* AppURL.toString() or AppURL.toHref().
* - In all other cases it navigates to the given URL via the redirect() helper, which routes through the
* core/safeRedirect action to guard against open-redirect vulnerabilities. If you have an AppURL you should always
* pass it, instead of AppURL.toString() or AppURL.toHref().
*/
interface AppNavigateState {
goBack: () => void;
Expand All @@ -42,7 +43,7 @@ export function useAppNavigate(): AppNavigateState {
return;
}

window.location.href = url.toString();
redirect(url.toString());

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@labkey-alan let me know what you think of this change. This would force the usages of navigate() to be internal redirect/navigations only...but I assume that was the intent and all usages are internal URLs. If there is a need for an external redirect / navigate, it was likely using window.location.href directly, right?

},
[rrNavigate]
);
Expand Down