mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-20 10:20:15 +01:00
🛡️ fix: Deep Clone MCPOptions for User MCP Connections (#7247)
* Fix: Prevent side effects in `processMCPEnv` by deep cloning MCPOptions The `processMCPEnv` function was modifying the original `MCPOptions` object, leading to unintended side effects where `LIBRECHAT_USER_ID` could be incorrectly shared across different users. This commit addresses this issue by performing a deep clone of the `MCPOptions` object before processing, ensuring that modifications are isolated and do not affect other users. * ci: Add tests for processMCPEnv to ensure deep cloning, user ID isolation and environment variable processing --------- Co-authored-by: Alex C <viennadd@users.noreply.github.com>
This commit is contained in:
parent
7c92cef2b7
commit
8e1012c5aa
2 changed files with 136 additions and 9 deletions
|
|
@ -96,28 +96,30 @@ export type MCPOptions = z.infer<typeof MCPOptionsSchema>;
|
|||
* @param {string} [userId] - The user ID
|
||||
* @returns {MCPOptions} - The processed object with environment variables replaced
|
||||
*/
|
||||
export function processMCPEnv(obj: MCPOptions, userId?: string): MCPOptions {
|
||||
export function processMCPEnv(obj: Readonly<MCPOptions>, userId?: string): MCPOptions {
|
||||
if (obj === null || obj === undefined) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if ('env' in obj && obj.env) {
|
||||
const newObj: MCPOptions = structuredClone(obj);
|
||||
|
||||
if ('env' in newObj && newObj.env) {
|
||||
const processedEnv: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(obj.env)) {
|
||||
for (const [key, value] of Object.entries(newObj.env)) {
|
||||
processedEnv[key] = extractEnvVariable(value);
|
||||
}
|
||||
obj.env = processedEnv;
|
||||
} else if ('headers' in obj && obj.headers) {
|
||||
newObj.env = processedEnv;
|
||||
} else if ('headers' in newObj && newObj.headers) {
|
||||
const processedHeaders: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(obj.headers)) {
|
||||
for (const [key, value] of Object.entries(newObj.headers)) {
|
||||
if (value === '{{LIBRECHAT_USER_ID}}' && userId != null && userId) {
|
||||
processedHeaders[key] = userId;
|
||||
continue;
|
||||
}
|
||||
processedHeaders[key] = extractEnvVariable(value);
|
||||
}
|
||||
obj.headers = processedHeaders;
|
||||
newObj.headers = processedHeaders;
|
||||
}
|
||||
|
||||
return obj;
|
||||
return newObj;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue