From a329d2f2bc56fce70f043443d64b0880e74788df Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 25 Mar 2026 17:54:19 -0300 Subject: [PATCH] fix(proxy): test endpoint resolves real credentials from DB via proxyId The proxy test button in Settings was always failing with 'Socks5 Authentication failed' because the frontend sent redacted credentials (***) from listProxies(). The backend received '***' as the password and tried to authenticate with it. Fix: Frontend now sends proxyId in the test request body. The test endpoint looks up the proxy from the DB with includeSecrets: true and uses the real stored credentials for the SOCKS5 handshake. Also: removed username/password from the frontend test payload since they are always redacted and useless for testing. --- .../components/ProxyRegistryManager.tsx | 3 +-- src/app/api/settings/proxy/test/route.ts | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx b/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx index c661204fed..df1e083630 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx @@ -209,12 +209,11 @@ export default function ProxyRegistryManager() { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ + proxyId: item.id, proxy: { type: item.type || "http", host: item.host, port: String(item.port || 8080), - username: item.username, - password: item.password, }, }), }); diff --git a/src/app/api/settings/proxy/test/route.ts b/src/app/api/settings/proxy/test/route.ts index b799852b7a..f74bd911e3 100644 --- a/src/app/api/settings/proxy/test/route.ts +++ b/src/app/api/settings/proxy/test/route.ts @@ -8,6 +8,7 @@ import { import { testProxySchema } from "@/shared/validation/schemas"; import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; import { createErrorResponse, createErrorResponseFromUnknown } from "@/lib/api/errorResponse"; +import { getProxyById } from "@/lib/localDb"; const BASE_SUPPORTED_PROXY_TYPES = new Set(["http", "https"]); @@ -56,7 +57,26 @@ export async function POST(request: Request) { type: "invalid_request", }); } - const { proxy } = validation.data; + let { proxy } = validation.data; + + // If a proxyId is provided, look up the real (non-redacted) credentials from DB. + // The frontend sends redacted credentials (***) from listProxies(), so we need + // the actual secrets for testing. + const body = rawBody as Record; + const proxyId = typeof body.proxyId === "string" ? body.proxyId.trim() : null; + if (proxyId) { + const dbProxy = await getProxyById(proxyId, { includeSecrets: true }); + if (dbProxy) { + proxy = { + ...proxy, + host: proxy.host || dbProxy.host, + port: proxy.port || String(dbProxy.port), + type: proxy.type || dbProxy.type, + username: dbProxy.username, + password: dbProxy.password, + }; + } + } const proxyType = String(proxy.type || "http").toLowerCase(); if (proxyType === "socks5" && !isSocks5ProxyEnabled()) {