fix(security): guard external hrefs and refine CSRF/auth-loading handling

- Add safeExternalHref(): only render http(s) URLs as clickable hrefs,
  blocking attacker-controlled template metadata from becoming
  javascript:/data: links.
- Refine CSRF header attachment and auth-loading state in the fetcher,
  api-tokens client, useAuth, and settings route.

Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
This commit is contained in:
naiba
2026-05-31 05:51:39 +00:00
co-authored by cloudcode
parent 964684f1bf
commit 013770bf46
5 changed files with 62 additions and 17 deletions
+15 -9
View File
@@ -26,7 +26,7 @@ import { Textarea } from "@/components/ui/textarea"
import { useAuth } from "@/hooks/useAuth"
import { useNotification } from "@/hooks/useNotfication"
import useSetting from "@/hooks/useSetting"
import { asOptionalField } from "@/lib/utils"
import { asOptionalField, safeExternalHref } from "@/lib/utils"
import { nezhaLang, settingCoverageTypes } from "@/types"
import { zodResolver } from "@hookform/resolvers/zod"
import { useEffect } from "react"
@@ -223,14 +223,20 @@ export default function SettingsPage() {
</div>
</SelectItem>
<div className="px-8 py-1">
<a
href={template.repository}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-blue-600 hover:text-blue-800 hover:underline"
>
{template.repository}
</a>
{safeExternalHref(template.repository) ? (
<a
href={safeExternalHref(template.repository)}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-blue-600 hover:text-blue-800 hover:underline"
>
{template.repository}
</a>
) : (
<span className="text-sm text-muted-foreground">
{template.repository}
</span>
)}
</div>
</div>
))}