mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-11-03 23:55:44 +00:00 
			
		
		
		
	feat: sanitize redirect URL
This commit is contained in:
		@@ -14,6 +14,7 @@
 | 
				
			|||||||
        "axios": "^1.9.0",
 | 
					        "axios": "^1.9.0",
 | 
				
			||||||
        "class-variance-authority": "^0.7.1",
 | 
					        "class-variance-authority": "^0.7.1",
 | 
				
			||||||
        "clsx": "^2.1.1",
 | 
					        "clsx": "^2.1.1",
 | 
				
			||||||
 | 
					        "dompurify": "^3.2.5",
 | 
				
			||||||
        "i18next": "^25.0.2",
 | 
					        "i18next": "^25.0.2",
 | 
				
			||||||
        "i18next-browser-languagedetector": "^8.0.5",
 | 
					        "i18next-browser-languagedetector": "^8.0.5",
 | 
				
			||||||
        "i18next-resources-to-backend": "^1.2.1",
 | 
					        "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/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=="],
 | 
					    "@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=="],
 | 
					    "@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=="],
 | 
					    "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=="],
 | 
					    "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=="],
 | 
					    "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
    "axios": "^1.9.0",
 | 
					    "axios": "^1.9.0",
 | 
				
			||||||
    "class-variance-authority": "^0.7.1",
 | 
					    "class-variance-authority": "^0.7.1",
 | 
				
			||||||
    "clsx": "^2.1.1",
 | 
					    "clsx": "^2.1.1",
 | 
				
			||||||
 | 
					    "dompurify": "^3.2.5",
 | 
				
			||||||
    "i18next": "^25.0.2",
 | 
					    "i18next": "^25.0.2",
 | 
				
			||||||
    "i18next-browser-languagedetector": "^8.0.5",
 | 
					    "i18next-browser-languagedetector": "^8.0.5",
 | 
				
			||||||
    "i18next-resources-to-backend": "^1.2.1",
 | 
					    "i18next-resources-to-backend": "^1.2.1",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import { useUserContext } from "@/context/user-context";
 | 
				
			|||||||
import { isValidUrl } from "@/lib/utils";
 | 
					import { isValidUrl } from "@/lib/utils";
 | 
				
			||||||
import { Trans, useTranslation } from "react-i18next";
 | 
					import { Trans, useTranslation } from "react-i18next";
 | 
				
			||||||
import { Navigate, useNavigate } from "react-router";
 | 
					import { Navigate, useNavigate } from "react-router";
 | 
				
			||||||
 | 
					import DOMPurify from "dompurify";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ContinuePage = () => {
 | 
					export const ContinuePage = () => {
 | 
				
			||||||
  const params = new URLSearchParams(window.location.search);
 | 
					  const params = new URLSearchParams(window.location.search);
 | 
				
			||||||
@@ -33,7 +34,7 @@ export const ContinuePage = () => {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (disableContinue) {
 | 
					  if (disableContinue) {
 | 
				
			||||||
    window.location.href = redirectURI;
 | 
					    window.location.href = DOMPurify.sanitize(redirectURI);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const navigate = useNavigate();
 | 
					  const navigate = useNavigate();
 | 
				
			||||||
@@ -60,7 +61,9 @@ export const ContinuePage = () => {
 | 
				
			|||||||
        </CardHeader>
 | 
					        </CardHeader>
 | 
				
			||||||
        <CardFooter className="flex flex-col items-stretch gap-2">
 | 
					        <CardFooter className="flex flex-col items-stretch gap-2">
 | 
				
			||||||
          <Button
 | 
					          <Button
 | 
				
			||||||
            onClick={() => (window.location.href = redirectURI)}
 | 
					            onClick={() =>
 | 
				
			||||||
 | 
					              (window.location.href = DOMPurify.sanitize(redirectURI))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            variant="destructive"
 | 
					            variant="destructive"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {t("continueTitle")}
 | 
					            {t("continueTitle")}
 | 
				
			||||||
@@ -92,7 +95,9 @@ export const ContinuePage = () => {
 | 
				
			|||||||
        </CardHeader>
 | 
					        </CardHeader>
 | 
				
			||||||
        <CardFooter className="flex flex-col items-stretch gap-2">
 | 
					        <CardFooter className="flex flex-col items-stretch gap-2">
 | 
				
			||||||
          <Button
 | 
					          <Button
 | 
				
			||||||
            onClick={() => (window.location.href = redirectURI)}
 | 
					            onClick={() =>
 | 
				
			||||||
 | 
					              (window.location.href = DOMPurify.sanitize(redirectURI))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            variant="warning"
 | 
					            variant="warning"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {t("continueTitle")}
 | 
					            {t("continueTitle")}
 | 
				
			||||||
@@ -112,7 +117,11 @@ export const ContinuePage = () => {
 | 
				
			|||||||
        <CardDescription>{t("continueSubtitle")}</CardDescription>
 | 
					        <CardDescription>{t("continueSubtitle")}</CardDescription>
 | 
				
			||||||
      </CardHeader>
 | 
					      </CardHeader>
 | 
				
			||||||
      <CardFooter className="flex flex-col items-stretch">
 | 
					      <CardFooter className="flex flex-col items-stretch">
 | 
				
			||||||
        <Button onClick={() => (window.location.href = redirectURI)}>
 | 
					        <Button
 | 
				
			||||||
 | 
					          onClick={() =>
 | 
				
			||||||
 | 
					            (window.location.href = DOMPurify.sanitize(redirectURI))
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          {t("continueTitle")}
 | 
					          {t("continueTitle")}
 | 
				
			||||||
        </Button>
 | 
					        </Button>
 | 
				
			||||||
      </CardFooter>
 | 
					      </CardFooter>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ export const appContextSchema = z.object({
 | 
				
			|||||||
    genericName: z.string(),
 | 
					    genericName: z.string(),
 | 
				
			||||||
    domain: z.string(),
 | 
					    domain: z.string(),
 | 
				
			||||||
    forgotPasswordMessage: z.string(),
 | 
					    forgotPasswordMessage: z.string(),
 | 
				
			||||||
    // oauthAutoRedirect: z.string(),
 | 
					    oauthAutoRedirect: z.string(),
 | 
				
			||||||
    backgroundImage: z.string(),
 | 
					    backgroundImage: z.string(),
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user