fix(security): harden BYO API header against SSRF and input abuse (#33)
* fix(security): harden BYO API header against SSRF and input abuse - Add lib/validateUrl.ts with HTTPS-only + public-IP enforcement, provider allowlist, IPv6 rejection, and userinfo-in-URL blocking. - Add lib/byoHeaders.ts — single source of truth for client-side BYO header construction (deduplicates app/page.tsx & app/play/page.tsx). - config.ts: validate BYO endpoints via isPublicUrl(), cap header at 2 KB, truncate apiKey/model strings, sanitize log output. - fetchWithRetry: default redirect to "manual" to block 302-to-intranet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(security): address Copilot review — trim endpoint, strip control chars, drop unused import - safeEndpoint: trim whitespace before URL validation - safeString: strip ASCII control characters to prevent header injection - play/page.tsx: remove unused BYO_STORAGE_KEY import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+1
-18
@@ -11,6 +11,7 @@ import {
|
||||
type Gender,
|
||||
} from "@/lib/options";
|
||||
import { readStoredTtsConfig } from "@/lib/clientTtsConfig";
|
||||
import { BYO_STORAGE_KEY, getByoHeaders } from "@/lib/byoHeaders";
|
||||
import { TtsKeyModal } from "@/components/TtsKeyModal";
|
||||
|
||||
/* ============================================================================
|
||||
@@ -749,8 +750,6 @@ const DEFAULT_BYO: ByoApiConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
const BYO_STORAGE_KEY = "infiplot:byoApi";
|
||||
|
||||
function normalizeByoSection(
|
||||
s: unknown,
|
||||
providers: Record<string, ByoProvider>,
|
||||
@@ -788,22 +787,6 @@ function loadByoConfig(): ByoApiConfig {
|
||||
}
|
||||
}
|
||||
|
||||
function getByoHeaders(): Record<string, string> {
|
||||
if (typeof window === "undefined") return {};
|
||||
try {
|
||||
const raw = localStorage.getItem(BYO_STORAGE_KEY);
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed.llm?.enabled || parsed.painter?.enabled) {
|
||||
return { "x-byo-api": raw };
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/* ---------- typewriter ---------- */
|
||||
|
||||
// 父组件持有当前 phrase 的索引(这样 start() 不输入时能用当前闪动的那句
|
||||
|
||||
Reference in New Issue
Block a user