From 28eea8d40c1f2115d4bd761749b7a095a3d51795 Mon Sep 17 00:00:00 2001 From: Stavros Date: Wed, 14 May 2025 20:08:04 +0300 Subject: [PATCH] feat: sanitize redirect URL --- frontend/bun.lock | 5 +++++ frontend/package.json | 1 + frontend/src/pages/continue-page.tsx | 17 +++++++++++++---- frontend/src/schemas/app-context-schema.ts | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/frontend/bun.lock b/frontend/bun.lock index 3b66053..232f34e 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -14,6 +14,7 @@ "axios": "^1.9.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "dompurify": "^3.2.5", "i18next": "^25.0.2", "i18next-browser-languagedetector": "^8.0.5", "i18next-resources-to-backend": "^1.2.1", @@ -357,6 +358,8 @@ "@types/react-dom": ["@types/react-dom@19.1.3", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg=="], + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.32.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.32.0", "@typescript-eslint/type-utils": "8.32.0", "@typescript-eslint/utils": "8.32.0", "@typescript-eslint/visitor-keys": "8.32.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ=="], @@ -479,6 +482,8 @@ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + "dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="], + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], diff --git a/frontend/package.json b/frontend/package.json index 8183466..527ea9f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "axios": "^1.9.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "dompurify": "^3.2.5", "i18next": "^25.0.2", "i18next-browser-languagedetector": "^8.0.5", "i18next-resources-to-backend": "^1.2.1", diff --git a/frontend/src/pages/continue-page.tsx b/frontend/src/pages/continue-page.tsx index a38307e..589f770 100644 --- a/frontend/src/pages/continue-page.tsx +++ b/frontend/src/pages/continue-page.tsx @@ -11,6 +11,7 @@ import { useUserContext } from "@/context/user-context"; import { isValidUrl } from "@/lib/utils"; import { Trans, useTranslation } from "react-i18next"; import { Navigate, useNavigate } from "react-router"; +import DOMPurify from "dompurify"; export const ContinuePage = () => { const params = new URLSearchParams(window.location.search); @@ -33,7 +34,7 @@ export const ContinuePage = () => { } if (disableContinue) { - window.location.href = redirectURI; + window.location.href = DOMPurify.sanitize(redirectURI); } const navigate = useNavigate(); @@ -60,7 +61,9 @@ export const ContinuePage = () => { diff --git a/frontend/src/schemas/app-context-schema.ts b/frontend/src/schemas/app-context-schema.ts index 60f557e..386143a 100644 --- a/frontend/src/schemas/app-context-schema.ts +++ b/frontend/src/schemas/app-context-schema.ts @@ -7,7 +7,7 @@ export const appContextSchema = z.object({ genericName: z.string(), domain: z.string(), forgotPasswordMessage: z.string(), - // oauthAutoRedirect: z.string(), + oauthAutoRedirect: z.string(), backgroundImage: z.string(), })