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.
| Package | Affected versions | Patched versions |
|---|---|---|
@lobehub/chatnpm | < 0.122.4 | 0.122.4 |
Affected products
1Patches
12184167f09ab🚑️ fix: fix plugin gateway auth (#1195)
9 files changed · +45 −260
src/app/api/errorResponse.test.ts+0 −0 renamedsrc/app/api/errorResponse.ts+0 −0 renamedsrc/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- github.com/advisories/GHSA-pf55-fj96-xf37ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-24566ghsaADVISORY
- github.com/lobehub/lobe-chat/commit/2184167f09ab68e4efa051ee984ea0c4e7c48fbdghsax_refsource_MISCWEB
- github.com/lobehub/lobe-chat/security/advisories/GHSA-pf55-fj96-xf37ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.