fix(web): avoid runtime proxy probes on public masked settings route (#1388)

This commit is contained in:
Kai (Tam Nhu) Tran
2026-05-23 22:37:49 -04:00
committed by GitHub
parent b35a23a6e4
commit fec84417a6
+18 -6
View File
@@ -22,7 +22,10 @@ import { deduplicateCcsHooks } from '../../utils/websearch/hook-utils';
import { removeCcsImageAnalyzerHooks } from '../../utils/hooks/image-analyzer-hook-utils'; import { removeCcsImageAnalyzerHooks } from '../../utils/hooks/image-analyzer-hook-utils';
import { resolveCliproxyBridgeMetadata } from '../../api/services'; import { resolveCliproxyBridgeMetadata } from '../../api/services';
import { requireLocalAccessWhenAuthDisabled } from '../middleware/auth-middleware'; import {
isLoopbackRemoteAddress,
requireLocalAccessWhenAuthDisabled,
} from '../middleware/auth-middleware';
import type { Settings } from '../../types/config'; import type { Settings } from '../../types/config';
import type { CLIProxyProvider } from '../../cliproxy/types'; import type { CLIProxyProvider } from '../../cliproxy/types';
import { mapExternalProviderName } from '../../cliproxy/provider-capabilities'; import { mapExternalProviderName } from '../../cliproxy/provider-capabilities';
@@ -43,6 +46,7 @@ import { resolveImageAnalysisRuntimeStatus } from '../../utils/hooks';
import { import {
getCcsDir, getCcsDir,
getImageAnalysisConfig, getImageAnalysisConfig,
isDashboardAuthEnabled,
loadConfigSafe, loadConfigSafe,
loadOrCreateUnifiedConfig, loadOrCreateUnifiedConfig,
loadSettings, loadSettings,
@@ -155,6 +159,14 @@ function requireSensitiveLocalAccess(req: Request, res: Response): boolean {
); );
} }
function canResolveSensitiveRuntimeStatus(req: Request): boolean {
if (isDashboardAuthEnabled()) {
return true;
}
return isLoopbackRemoteAddress(req.socket.remoteAddress);
}
function classifyConfigSaveFailure(error: unknown): { statusCode: number; message: string } { function classifyConfigSaveFailure(error: unknown): { statusCode: number; message: string } {
const message = error instanceof Error ? error.message.toLowerCase() : ''; const message = error instanceof Error ? error.message.toLowerCase() : '';
@@ -498,17 +510,17 @@ router.get('/:profile', async (req: Request, res: Response): Promise<void> => {
const stat = fs.statSync(settingsPath); const stat = fs.statSync(settingsPath);
const masked = maskApiKeys(settings); const masked = maskApiKeys(settings);
const imageAnalysisStatus = canResolveSensitiveRuntimeStatus(req)
? await resolveImageAnalysisStatusForProfile(profile, settings, settingsPath)
: null;
res.json({ res.json({
profile, profile,
settings: masked, settings: masked,
mtime: stat.mtime.getTime(), mtime: stat.mtime.getTime(),
path: settingsPath, path: settingsPath,
cliproxyBridge: resolveCliproxyBridgeMetadata(settings), cliproxyBridge: resolveCliproxyBridgeMetadata(settings),
imageAnalysisStatus: await resolveImageAnalysisStatusForProfile( imageAnalysisStatus,
profile,
settings,
settingsPath
),
}); });
} catch (error) { } catch (error) {
respondInternalError(res, error, 'Internal server error.'); respondInternalError(res, error, 'Internal server error.');