VYPR
Moderate severityNVD Advisory· Published Jan 31, 2024· Updated Jun 17, 2025

Lobe Chat unauthorized access to plugins

CVE-2024-24566

Description

Lobe Chat is a chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. When the application is password-protected (deployed with the ACCESS_CODE option), it is possible to access plugins without proper authorization (without password). This vulnerability is patched in 0.122.4.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@lobehub/chatnpm
< 0.122.40.122.4

Affected products

1

Patches

1
2184167f09ab

🚑️ fix: fix plugin gateway auth (#1195)

https://github.com/lobehub/lobe-chatArvin XuJan 30, 2024via ghsa
9 files changed · +45 260
  • src/app/api/errorResponse.test.ts+0 0 renamed
  • src/app/api/errorResponse.ts+0 0 renamed
  • src/app/api/openai/chat/createChatCompletion.ts+1 1 modified
    @@ -4,7 +4,7 @@ import OpenAI from 'openai';
     import { ChatErrorType } from '@/types/fetch';
     import { OpenAIChatStreamPayload } from '@/types/openai/chat';
     
    -import { createErrorResponse } from '../errorResponse';
    +import { createErrorResponse } from '../../errorResponse';
     import { desensitizeUrl } from './desensitizeUrl';
     
     interface CreateChatCompletionOptions {
    
  • src/app/api/openai/createBizOpenAI/index.ts+1 1 modified
    @@ -5,7 +5,7 @@ import { getServerConfig } from '@/config/server';
     import { getOpenAIAuthFromRequest } from '@/const/fetch';
     import { ChatErrorType, ErrorType } from '@/types/fetch';
     
    -import { createErrorResponse } from '../errorResponse';
    +import { createErrorResponse } from '../../errorResponse';
     import { createAzureOpenai } from './createAzureOpenai';
     import { createOpenai } from './createOpenai';
     
    
  • src/app/api/plugin/gateway/route.ts+31 5 modified
    @@ -1,13 +1,39 @@
     import { createGatewayOnEdgeRuntime } from '@lobehub/chat-plugins-gateway';
     
    -import { parserPluginSettings } from '@/app/api/plugin/gateway/settings';
    +import { createErrorResponse } from '@/app/api/errorResponse';
     import { getServerConfig } from '@/config/server';
    +import { getOpenAIAuthFromRequest } from '@/const/fetch';
    +import { ChatErrorType, ErrorType } from '@/types/fetch';
    +
    +import { parserPluginSettings } from './settings';
    +
    +const checkAuth = (accessCode: string | null) => {
    +  const { ACCESS_CODES } = getServerConfig();
    +
    +  // if accessCode doesn't exist
    +  if (!ACCESS_CODES.length) return { auth: true };
    +
    +  if (!accessCode || !ACCESS_CODES.includes(accessCode)) {
    +    return { auth: false, error: ChatErrorType.InvalidAccessCode };
    +  }
    +
    +  return { auth: true };
    +};
     
     const { PLUGINS_INDEX_URL: pluginsIndexUrl, PLUGIN_SETTINGS } = getServerConfig();
     
     const defaultPluginSettings = parserPluginSettings(PLUGIN_SETTINGS);
     
    -export const POST = createGatewayOnEdgeRuntime({
    -  defaultPluginSettings,
    -  pluginsIndexUrl,
    -});
    +const handler = createGatewayOnEdgeRuntime({ defaultPluginSettings, pluginsIndexUrl });
    +
    +export const POST = async (req: Request) => {
    +  const { accessCode } = getOpenAIAuthFromRequest(req);
    +
    +  const result = checkAuth(accessCode);
    +
    +  if (!result.auth) {
    +    return createErrorResponse(result.error as ErrorType);
    +  }
    +
    +  return handler(req);
    +};
    
  • src/app/chat/features/ChatHeader/SettingButton.tsx+1 1 modified
    @@ -27,7 +27,7 @@ const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
               });
               router.push('/settings/agent');
             } else {
    -          router.push(pathString('/chat/settings', { hash: location.hash }));
    +          router.push(pathString('/chat/settings', { search: location.search }));
             }
           }}
           size={mobile ? MOBILE_HEADER_ICON_SIZE : DESKTOP_HEADER_ICON_SIZE}
    
  • src/app/chat/settings/(desktop)/index.tsx+9 5 modified
    @@ -3,6 +3,7 @@
     import dynamic from 'next/dynamic';
     import { FC, memo } from 'react';
     
    +import SessionHydration from '@/app/chat/components/SessionHydration';
     import ResponsiveIndex from '@/components/ResponsiveIndex';
     
     import EditPage from '../features/EditPage';
    @@ -11,11 +12,14 @@ import Layout from './layout.desktop';
     const Mobile: FC = dynamic(() => import('../(mobile)'), { ssr: false }) as FC;
     
     const ChatSettings = memo(() => (
    -  <ResponsiveIndex Mobile={Mobile}>
    -    <Layout>
    -      <EditPage />
    -    </Layout>
    -  </ResponsiveIndex>
    +  <>
    +    <ResponsiveIndex Mobile={Mobile}>
    +      <Layout>
    +        <EditPage />
    +      </Layout>
    +    </ResponsiveIndex>
    +    <SessionHydration />
    +  </>
     ));
     
     export default ChatSettings;
    
  • src/services/chat.ts+2 1 modified
    @@ -91,7 +91,8 @@ class ChatService {
     
         const res = await fetch(gatewayURL ?? PLUGINS_URLS.gateway, {
           body: JSON.stringify({ ...params, manifest }),
    -      headers: createHeadersWithPluginSettings(settings),
    +      // TODO: we can have a better auth way
    +      headers: createHeadersWithPluginSettings(settings, createHeaderWithOpenAI()),
           method: 'POST',
           signal: options?.signal,
         });
    
  • src/store/global/slices/settings/__snapshots__/selectors.test.ts.snap+0 246 removed
    @@ -1,246 +0,0 @@
    -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
    -
    -exports[`settingsSelectors > CUSTOM_MODELS > custom deletion, addition, and renaming of models 1`] = `
    -[
    -  {
    -    "displayName": "llama",
    -    "name": "llama",
    -  },
    -  {
    -    "displayName": "claude-2",
    -    "name": "claude-2",
    -  },
    -  {
    -    "displayName": "gpt-4-32k",
    -    "name": "gpt-4-1106-preview",
    -  },
    -]
    -`;
    -
    -exports[`settingsSelectors > CUSTOM_MODELS > duplicate naming model 1`] = `
    -[
    -  {
    -    "displayName": "gpt-3.5-turbo",
    -    "name": "gpt-3.5-turbo",
    -  },
    -  {
    -    "displayName": "gpt-3.5-turbo-1106",
    -    "name": "gpt-3.5-turbo-1106",
    -  },
    -  {
    -    "displayName": "gpt-3.5-turbo-16k",
    -    "name": "gpt-3.5-turbo-16k",
    -  },
    -  {
    -    "displayName": "gpt-4",
    -    "name": "gpt-4",
    -  },
    -  {
    -    "displayName": "gpt-4-32k",
    -    "name": "gpt-4-32k",
    -  },
    -  {
    -    "displayName": "gpt-4-vision-preview",
    -    "name": "gpt-4-vision-preview",
    -  },
    -  {
    -    "displayName": "gpt-4-32k",
    -    "name": "gpt-4-1106-preview",
    -  },
    -]
    -`;
    -
    -exports[`settingsSelectors > CUSTOM_MODELS > only add the model 1`] = `
    -[
    -  {
    -    "displayName": "gpt-3.5-turbo",
    -    "name": "gpt-3.5-turbo",
    -  },
    -  {
    -    "displayName": "gpt-3.5-turbo-1106",
    -    "name": "gpt-3.5-turbo-1106",
    -  },
    -  {
    -    "displayName": "gpt-3.5-turbo-16k",
    -    "name": "gpt-3.5-turbo-16k",
    -  },
    -  {
    -    "displayName": "gpt-4",
    -    "name": "gpt-4",
    -  },
    -  {
    -    "displayName": "gpt-4-32k",
    -    "name": "gpt-4-32k",
    -  },
    -  {
    -    "displayName": "gpt-4-1106-preview",
    -    "name": "gpt-4-1106-preview",
    -  },
    -  {
    -    "displayName": "gpt-4-vision-preview",
    -    "name": "gpt-4-vision-preview",
    -  },
    -  {
    -    "displayName": "model1",
    -    "name": "model1",
    -  },
    -  {
    -    "displayName": "model2",
    -    "name": "model2",
    -  },
    -  {
    -    "displayName": "model3",
    -    "name": "model3",
    -  },
    -  {
    -    "displayName": "model4",
    -    "name": "model4",
    -  },
    -]
    -`;
    -
    -exports[`settingsSelectors > currentSettings > should merge DEFAULT_SETTINGS and s.settings correctly 1`] = `
    -{
    -  "avatar": "avatar.jpg",
    -  "defaultAgent": {
    -    "config": {
    -      "autoCreateTopicThreshold": 2,
    -      "displayMode": "chat",
    -      "enableAutoCreateTopic": true,
    -      "historyCount": 1,
    -      "model": "gpt-3.5-turbo",
    -      "params": {
    -        "frequency_penalty": 0,
    -        "presence_penalty": 0,
    -        "temperature": 0.6,
    -        "top_p": 1,
    -      },
    -      "plugins": [],
    -      "systemRole": "",
    -      "tts": {
    -        "showAllLocaleVoice": false,
    -        "sttLocale": "auto",
    -        "ttsService": "openai",
    -        "voice": {
    -          "openai": "alloy",
    -        },
    -      },
    -    },
    -    "meta": {
    -      "avatar": "Default Agent",
    -      "description": "Default agent for testing",
    -    },
    -  },
    -  "fontSize": 14,
    -  "language": "en-US",
    -  "languageModel": {
    -    "openAI": {
    -      "OPENAI_API_KEY": "openai-api-key",
    -      "endpoint": "https://openai-endpoint.com",
    -      "models": [
    -        "gpt-3.5-turbo",
    -      ],
    -    },
    -  },
    -  "neutralColor": "sand",
    -  "password": "password123",
    -  "primaryColor": "blue",
    -  "themeMode": "light",
    -  "tool": {
    -    "dalle": {
    -      "autoGenerate": false,
    -    },
    -  },
    -  "tts": {
    -    "openAI": {
    -      "sttModel": "whisper-1",
    -      "ttsModel": "tts-1",
    -    },
    -    "sttAutoStop": true,
    -    "sttServer": "openai",
    -  },
    -}
    -`;
    -
    -exports[`settingsSelectors > currentTTS > should merge DEFAULT_TTS_CONFIG and s.settings.tts correctly 1`] = `
    -{
    -  "openAI": {
    -    "sttModel": "whisper-2",
    -    "ttsModel": "tts-1",
    -  },
    -  "sttAutoStop": false,
    -  "sttServer": "openai",
    -}
    -`;
    -
    -exports[`settingsSelectors > dalleConfig > should return the dalle configuration 1`] = `
    -{
    -  "apiKey": "dalle-api-key",
    -  "autoGenerate": true,
    -}
    -`;
    -
    -exports[`settingsSelectors > defaultAgent > should merge DEFAULT_AGENT and s.settings.defaultAgent correctly 1`] = `
    -{
    -  "config": {
    -    "autoCreateTopicThreshold": 2,
    -    "displayMode": "chat",
    -    "enableAutoCreateTopic": true,
    -    "historyCount": 1,
    -    "model": "gpt-3.5-turbo",
    -    "params": {
    -      "frequency_penalty": 0,
    -      "presence_penalty": 0,
    -      "temperature": 0.6,
    -      "top_p": 1,
    -    },
    -    "plugins": [],
    -    "systemRole": "user",
    -    "tts": {
    -      "showAllLocaleVoice": false,
    -      "sttLocale": "auto",
    -      "ttsService": "openai",
    -      "voice": {
    -        "openai": "alloy",
    -      },
    -    },
    -  },
    -  "meta": {
    -    "avatar": "agent-avatar.jpg",
    -    "description": "Test agent",
    -  },
    -}
    -`;
    -
    -exports[`settingsSelectors > defaultAgentConfig > should merge DEFAULT_AGENT_CONFIG and defaultAgent(s).config correctly 1`] = `
    -{
    -  "autoCreateTopicThreshold": 2,
    -  "displayMode": "chat",
    -  "enableAutoCreateTopic": true,
    -  "historyCount": 1,
    -  "model": "gpt-3.5-turbo",
    -  "params": {
    -    "frequency_penalty": 0,
    -    "presence_penalty": 0,
    -    "temperature": 0.7,
    -    "top_p": 1,
    -  },
    -  "plugins": [],
    -  "systemRole": "user",
    -  "tts": {
    -    "showAllLocaleVoice": false,
    -    "sttLocale": "auto",
    -    "ttsService": "openai",
    -    "voice": {
    -      "openai": "alloy",
    -    },
    -  },
    -}
    -`;
    -
    -exports[`settingsSelectors > defaultAgentMeta > should merge DEFAULT_AGENT_META and defaultAgent(s).meta correctly 1`] = `
    -{
    -  "avatar": "agent-avatar.jpg",
    -  "description": "Test agent",
    -}
    -`;
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.