fix(security): restrict local connector endpoints

This commit is contained in:
ZacharyZhang-NY committed 2026-05-15 00:43:45 -04:00
1 parent fa19e95f19
commit 84b92c859e
12 files changed
+158 -18

No files matched your search

@@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { FloppyDisk } from "../../ui/icons";
import type { ConnectorCatalogEntry } from "@shared/connector-catalog";
import type { CredentialSummary } from "@shared/contracts/schemas-credentials";
import { isLocalConnectorBaseUrl, type CredentialSummary } from "@shared/contracts/schemas-credentials";
import type { TranslationFn } from "../../../i18n";
import {
InlineFeedback,
@@ -23,8 +23,8 @@ interface LocalProviderCardProps {
* Onboarding card for local OpenAI-compatible servers (Ollama, LM Studio).
*
* The catalog supplies a sensible default URL per entry; the user can
* override it to point at a non-default port, a remote machine, or a
* reverse proxy. The card never asks for an API key — local servers
* override it to point at a private LAN server or a non-default port.
* The card never asks for an API key — local servers
* accept any bearer value, so the credential resolver supplies the
* connector id as a non-empty placeholder for the OpenAI SDK.
*/
@@ -65,9 +65,7 @@ export function LocalProviderCard({
setFeedback(t("onboarding.providers.baseUrlRequired"));
return;
}
try {
new URL(trimmed);
} catch {
if (!isLocalConnectorBaseUrl(trimmed)) {
setFeedback(t("onboarding.providers.baseUrlInvalid"));
return;
}
@@ -1,4 +1,5 @@
import { useState } from "react";
import { isLocalConnectorBaseUrl } from "@shared/contracts/schemas-credentials";
import { ActionButton, Input } from "../../ui";
import { useT } from "../../../i18n";
@@ -22,9 +23,7 @@ export function LocalForm({ connectorId, defaultBaseUrl, onSaved }: Props) {
const handleSubmit = async () => {
if (!desktop || !canSave) return;
try {
new URL(trimmed);
} catch {
if (!isLocalConnectorBaseUrl(trimmed)) {
setError(t("onboarding.providers.baseUrlInvalid"));
return;
}
+1 -1
View File
@@ -191,7 +191,7 @@ export const en: Record<string, string> = {
"onboarding.providers.apiKeyReplacePlaceholder": "Leave empty to keep the current key",
"onboarding.providers.baseUrlLabel": "Base URL",
"onboarding.providers.baseUrlRequired": "Enter the local server URL before saving.",
"onboarding.providers.baseUrlInvalid": "Enter a valid HTTP or HTTPS URL.",
"onboarding.providers.baseUrlInvalid": "Enter a loopback or private-network HTTP(S) URL.",
"onboarding.providers.save": "Save",
"onboarding.providers.saving": "Saving…",
"onboarding.providers.saved": "Saved.",
+1 -1
View File
@@ -191,7 +191,7 @@ export const zh: Record<string, string> = {
"onboarding.providers.apiKeyReplacePlaceholder": "保持现有 Key 请留空",
"onboarding.providers.baseUrlLabel": "服务地址",
"onboarding.providers.baseUrlRequired": "请填入本地服务地址后再保存。",
"onboarding.providers.baseUrlInvalid": "请输入合法的 HTTP 或 HTTPS 地址。",
"onboarding.providers.baseUrlInvalid": "请输入本机或私有网络 HTTP(S) 地址。",
"onboarding.providers.save": "保存",
"onboarding.providers.saving": "保存中…",
"onboarding.providers.saved": "已保存。",