LibreChat/api/server/middleware/accessResources/canAccessAgentFromBody.js

193 lines
6.1 KiB
JavaScript
Raw Normal View History

const { logger } = require('@librechat/data-schemas');
⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) * 🌊 feat: Implement multi-conversation feature with added conversation context and payload adjustments * refactor: Replace isSubmittingFamily with isSubmitting across message components for consistency * feat: Add loadAddedAgent and processAddedConvo for multi-conversation agent execution * refactor: Update ContentRender usage to conditionally render PlaceholderRow based on isLast and isSubmitting * WIP: first pass, sibling index * feat: Enhance multi-conversation support with agent tracking and display improvements * refactor: Introduce isEphemeralAgentId utility and update related logic for agent handling * refactor: Implement createDualMessageContent utility for sibling message display and enhance useStepHandler for added conversations * refactor: duplicate tools for added agent if ephemeral and primary agent is also ephemeral * chore: remove deprecated multimessage rendering * refactor: enhance dual message content creation and agent handling for parallel rendering * refactor: streamline message rendering and submission handling by removing unused state and optimizing conditional logic * refactor: adjust content handling in parallel mode to utilize existing content for improved agent display * refactor: update @librechat/agents dependency to version 3.0.53 * refactor: update @langchain/core and @librechat/agents dependencies to latest versions * refactor: remove deprecated @langchain/core dependency from package.json * chore: remove unused SearchToolConfig and GetSourcesParams types from web.ts * refactor: remove unused message properties from Message component * refactor: enhance parallel content handling with groupId support in ContentParts and useStepHandler * refactor: implement parallel content styling in Message, MessageRender, and ContentRender components. use explicit model name * refactor: improve agent ID handling in createDualMessageContent for dual message display * refactor: simplify title generation in AddedConvo by removing unused sender and preset logic * refactor: replace string interpolation with cn utility for className in HoverButtons component * refactor: enhance agent ID handling by adding suffix management for parallel agents and updating related components * refactor: enhance column ordering in ContentParts by sorting agents with suffix management * refactor: update @librechat/agents dependency to version 3.0.55 * feat: implement parallel content rendering with metadata support - Added `ParallelContentRenderer` and `ParallelColumns` components for rendering messages in parallel based on groupId and agentId. - Introduced `contentMetadataMap` to store metadata for each content part, allowing efficient parallel content detection. - Updated `Message` and `ContentRender` components to utilize the new metadata structure for rendering. - Modified `useStepHandler` to manage content indices and metadata during message processing. - Enhanced `IJobStore` interface and its implementations to support storing and retrieving content metadata. - Updated data schemas to include `contentMetadataMap` for messages, enabling multi-agent and parallel execution scenarios. * refactor: update @librechat/agents dependency to version 3.0.56 * refactor: remove unused EPHEMERAL_AGENT_ID constant and simplify agent ID check * refactor: enhance multi-agent message processing and primary agent determination * refactor: implement branch message functionality for parallel responses * refactor: integrate added conversation retrieval into message editing and regeneration processes * refactor: remove unused isCard and isMultiMessage props from MessageRender and ContentRender components * refactor: update @librechat/agents dependency to version 3.0.60 * refactor: replace usage of EPHEMERAL_AGENT_ID constant with isEphemeralAgentId function for improved clarity and consistency * refactor: standardize agent ID format in tests for consistency * chore: move addedConvo property to the correct position in payload construction * refactor: rename agent_id values in loadAgent tests for clarity * chore: reorder props in ContentParts component for improved readability * refactor: rename variable 'content' to 'result' for clarity in RedisJobStore tests * refactor: streamline useMessageActions by removing duplicate handleFeedback assignment * chore: revert placeholder rendering logic MessageRender and ContentRender components to original * refactor: implement useContentMetadata hook for optimized content metadata handling * refactor: remove contentMetadataMap and related logic from the codebase and revert back to agentId/groupId in content parts - Eliminated contentMetadataMap from various components and services, simplifying the handling of message content. - Updated functions to directly access agentId and groupId from content parts instead of relying on a separate metadata map. - Adjusted related hooks and components to reflect the removal of contentMetadataMap, ensuring consistent handling of message content. - Updated tests and documentation to align with the new structure of message content handling. * refactor: remove logging from groupParallelContent function to clean up output * refactor: remove model parameter from TBranchMessageRequest type for simplification * refactor: enhance branch message creation by stripping metadata for standalone content * chore: streamline branch message creation by simplifying content filtering and removing unnecessary metadata checks * refactor: include attachments in branch message creation for improved content handling * refactor: streamline agent content processing by consolidating primary agent identification and filtering logic * refactor: simplify multi-agent message processing by creating a dedicated mapping method and enhancing content filtering * refactor: remove unused parameter from loadEphemeralAgent function for cleaner code * refactor: update groupId handling in metadata to only set when provided by the server
2025-12-25 01:43:54 -05:00
const {
Constants,
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
Permissions,
⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) * 🌊 feat: Implement multi-conversation feature with added conversation context and payload adjustments * refactor: Replace isSubmittingFamily with isSubmitting across message components for consistency * feat: Add loadAddedAgent and processAddedConvo for multi-conversation agent execution * refactor: Update ContentRender usage to conditionally render PlaceholderRow based on isLast and isSubmitting * WIP: first pass, sibling index * feat: Enhance multi-conversation support with agent tracking and display improvements * refactor: Introduce isEphemeralAgentId utility and update related logic for agent handling * refactor: Implement createDualMessageContent utility for sibling message display and enhance useStepHandler for added conversations * refactor: duplicate tools for added agent if ephemeral and primary agent is also ephemeral * chore: remove deprecated multimessage rendering * refactor: enhance dual message content creation and agent handling for parallel rendering * refactor: streamline message rendering and submission handling by removing unused state and optimizing conditional logic * refactor: adjust content handling in parallel mode to utilize existing content for improved agent display * refactor: update @librechat/agents dependency to version 3.0.53 * refactor: update @langchain/core and @librechat/agents dependencies to latest versions * refactor: remove deprecated @langchain/core dependency from package.json * chore: remove unused SearchToolConfig and GetSourcesParams types from web.ts * refactor: remove unused message properties from Message component * refactor: enhance parallel content handling with groupId support in ContentParts and useStepHandler * refactor: implement parallel content styling in Message, MessageRender, and ContentRender components. use explicit model name * refactor: improve agent ID handling in createDualMessageContent for dual message display * refactor: simplify title generation in AddedConvo by removing unused sender and preset logic * refactor: replace string interpolation with cn utility for className in HoverButtons component * refactor: enhance agent ID handling by adding suffix management for parallel agents and updating related components * refactor: enhance column ordering in ContentParts by sorting agents with suffix management * refactor: update @librechat/agents dependency to version 3.0.55 * feat: implement parallel content rendering with metadata support - Added `ParallelContentRenderer` and `ParallelColumns` components for rendering messages in parallel based on groupId and agentId. - Introduced `contentMetadataMap` to store metadata for each content part, allowing efficient parallel content detection. - Updated `Message` and `ContentRender` components to utilize the new metadata structure for rendering. - Modified `useStepHandler` to manage content indices and metadata during message processing. - Enhanced `IJobStore` interface and its implementations to support storing and retrieving content metadata. - Updated data schemas to include `contentMetadataMap` for messages, enabling multi-agent and parallel execution scenarios. * refactor: update @librechat/agents dependency to version 3.0.56 * refactor: remove unused EPHEMERAL_AGENT_ID constant and simplify agent ID check * refactor: enhance multi-agent message processing and primary agent determination * refactor: implement branch message functionality for parallel responses * refactor: integrate added conversation retrieval into message editing and regeneration processes * refactor: remove unused isCard and isMultiMessage props from MessageRender and ContentRender components * refactor: update @librechat/agents dependency to version 3.0.60 * refactor: replace usage of EPHEMERAL_AGENT_ID constant with isEphemeralAgentId function for improved clarity and consistency * refactor: standardize agent ID format in tests for consistency * chore: move addedConvo property to the correct position in payload construction * refactor: rename agent_id values in loadAgent tests for clarity * chore: reorder props in ContentParts component for improved readability * refactor: rename variable 'content' to 'result' for clarity in RedisJobStore tests * refactor: streamline useMessageActions by removing duplicate handleFeedback assignment * chore: revert placeholder rendering logic MessageRender and ContentRender components to original * refactor: implement useContentMetadata hook for optimized content metadata handling * refactor: remove contentMetadataMap and related logic from the codebase and revert back to agentId/groupId in content parts - Eliminated contentMetadataMap from various components and services, simplifying the handling of message content. - Updated functions to directly access agentId and groupId from content parts instead of relying on a separate metadata map. - Adjusted related hooks and components to reflect the removal of contentMetadataMap, ensuring consistent handling of message content. - Updated tests and documentation to align with the new structure of message content handling. * refactor: remove logging from groupParallelContent function to clean up output * refactor: remove model parameter from TBranchMessageRequest type for simplification * refactor: enhance branch message creation by stripping metadata for standalone content * chore: streamline branch message creation by simplifying content filtering and removing unnecessary metadata checks * refactor: include attachments in branch message creation for improved content handling * refactor: streamline agent content processing by consolidating primary agent identification and filtering logic * refactor: simplify multi-agent message processing by creating a dedicated mapping method and enhancing content filtering * refactor: remove unused parameter from loadEphemeralAgent function for cleaner code * refactor: update groupId handling in metadata to only set when provided by the server
2025-12-25 01:43:54 -05:00
ResourceType,
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
SystemRoles,
PermissionTypes,
⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) * 🌊 feat: Implement multi-conversation feature with added conversation context and payload adjustments * refactor: Replace isSubmittingFamily with isSubmitting across message components for consistency * feat: Add loadAddedAgent and processAddedConvo for multi-conversation agent execution * refactor: Update ContentRender usage to conditionally render PlaceholderRow based on isLast and isSubmitting * WIP: first pass, sibling index * feat: Enhance multi-conversation support with agent tracking and display improvements * refactor: Introduce isEphemeralAgentId utility and update related logic for agent handling * refactor: Implement createDualMessageContent utility for sibling message display and enhance useStepHandler for added conversations * refactor: duplicate tools for added agent if ephemeral and primary agent is also ephemeral * chore: remove deprecated multimessage rendering * refactor: enhance dual message content creation and agent handling for parallel rendering * refactor: streamline message rendering and submission handling by removing unused state and optimizing conditional logic * refactor: adjust content handling in parallel mode to utilize existing content for improved agent display * refactor: update @librechat/agents dependency to version 3.0.53 * refactor: update @langchain/core and @librechat/agents dependencies to latest versions * refactor: remove deprecated @langchain/core dependency from package.json * chore: remove unused SearchToolConfig and GetSourcesParams types from web.ts * refactor: remove unused message properties from Message component * refactor: enhance parallel content handling with groupId support in ContentParts and useStepHandler * refactor: implement parallel content styling in Message, MessageRender, and ContentRender components. use explicit model name * refactor: improve agent ID handling in createDualMessageContent for dual message display * refactor: simplify title generation in AddedConvo by removing unused sender and preset logic * refactor: replace string interpolation with cn utility for className in HoverButtons component * refactor: enhance agent ID handling by adding suffix management for parallel agents and updating related components * refactor: enhance column ordering in ContentParts by sorting agents with suffix management * refactor: update @librechat/agents dependency to version 3.0.55 * feat: implement parallel content rendering with metadata support - Added `ParallelContentRenderer` and `ParallelColumns` components for rendering messages in parallel based on groupId and agentId. - Introduced `contentMetadataMap` to store metadata for each content part, allowing efficient parallel content detection. - Updated `Message` and `ContentRender` components to utilize the new metadata structure for rendering. - Modified `useStepHandler` to manage content indices and metadata during message processing. - Enhanced `IJobStore` interface and its implementations to support storing and retrieving content metadata. - Updated data schemas to include `contentMetadataMap` for messages, enabling multi-agent and parallel execution scenarios. * refactor: update @librechat/agents dependency to version 3.0.56 * refactor: remove unused EPHEMERAL_AGENT_ID constant and simplify agent ID check * refactor: enhance multi-agent message processing and primary agent determination * refactor: implement branch message functionality for parallel responses * refactor: integrate added conversation retrieval into message editing and regeneration processes * refactor: remove unused isCard and isMultiMessage props from MessageRender and ContentRender components * refactor: update @librechat/agents dependency to version 3.0.60 * refactor: replace usage of EPHEMERAL_AGENT_ID constant with isEphemeralAgentId function for improved clarity and consistency * refactor: standardize agent ID format in tests for consistency * chore: move addedConvo property to the correct position in payload construction * refactor: rename agent_id values in loadAgent tests for clarity * chore: reorder props in ContentParts component for improved readability * refactor: rename variable 'content' to 'result' for clarity in RedisJobStore tests * refactor: streamline useMessageActions by removing duplicate handleFeedback assignment * chore: revert placeholder rendering logic MessageRender and ContentRender components to original * refactor: implement useContentMetadata hook for optimized content metadata handling * refactor: remove contentMetadataMap and related logic from the codebase and revert back to agentId/groupId in content parts - Eliminated contentMetadataMap from various components and services, simplifying the handling of message content. - Updated functions to directly access agentId and groupId from content parts instead of relying on a separate metadata map. - Adjusted related hooks and components to reflect the removal of contentMetadataMap, ensuring consistent handling of message content. - Updated tests and documentation to align with the new structure of message content handling. * refactor: remove logging from groupParallelContent function to clean up output * refactor: remove model parameter from TBranchMessageRequest type for simplification * refactor: enhance branch message creation by stripping metadata for standalone content * chore: streamline branch message creation by simplifying content filtering and removing unnecessary metadata checks * refactor: include attachments in branch message creation for improved content handling * refactor: streamline agent content processing by consolidating primary agent identification and filtering logic * refactor: simplify multi-agent message processing by creating a dedicated mapping method and enhancing content filtering * refactor: remove unused parameter from loadEphemeralAgent function for cleaner code * refactor: update groupId handling in metadata to only set when provided by the server
2025-12-25 01:43:54 -05:00
isAgentsEndpoint,
isEphemeralAgentId,
} = require('librechat-data-provider');
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
const { checkPermission } = require('~/server/services/PermissionService');
const { canAccessResource } = require('./canAccessResource');
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
const { getRoleByName } = require('~/models/Role');
const { getAgent } = require('~/models/Agent');
/**
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
* Resolves custom agent ID (e.g., "agent_abc123") to a MongoDB document.
* @param {string} agentCustomId - Custom agent ID from request body
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
* @returns {Promise<Object|null>} Agent document with _id field, or null if ephemeral/not found
*/
const resolveAgentIdFromBody = async (agentCustomId) => {
⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) * 🌊 feat: Implement multi-conversation feature with added conversation context and payload adjustments * refactor: Replace isSubmittingFamily with isSubmitting across message components for consistency * feat: Add loadAddedAgent and processAddedConvo for multi-conversation agent execution * refactor: Update ContentRender usage to conditionally render PlaceholderRow based on isLast and isSubmitting * WIP: first pass, sibling index * feat: Enhance multi-conversation support with agent tracking and display improvements * refactor: Introduce isEphemeralAgentId utility and update related logic for agent handling * refactor: Implement createDualMessageContent utility for sibling message display and enhance useStepHandler for added conversations * refactor: duplicate tools for added agent if ephemeral and primary agent is also ephemeral * chore: remove deprecated multimessage rendering * refactor: enhance dual message content creation and agent handling for parallel rendering * refactor: streamline message rendering and submission handling by removing unused state and optimizing conditional logic * refactor: adjust content handling in parallel mode to utilize existing content for improved agent display * refactor: update @librechat/agents dependency to version 3.0.53 * refactor: update @langchain/core and @librechat/agents dependencies to latest versions * refactor: remove deprecated @langchain/core dependency from package.json * chore: remove unused SearchToolConfig and GetSourcesParams types from web.ts * refactor: remove unused message properties from Message component * refactor: enhance parallel content handling with groupId support in ContentParts and useStepHandler * refactor: implement parallel content styling in Message, MessageRender, and ContentRender components. use explicit model name * refactor: improve agent ID handling in createDualMessageContent for dual message display * refactor: simplify title generation in AddedConvo by removing unused sender and preset logic * refactor: replace string interpolation with cn utility for className in HoverButtons component * refactor: enhance agent ID handling by adding suffix management for parallel agents and updating related components * refactor: enhance column ordering in ContentParts by sorting agents with suffix management * refactor: update @librechat/agents dependency to version 3.0.55 * feat: implement parallel content rendering with metadata support - Added `ParallelContentRenderer` and `ParallelColumns` components for rendering messages in parallel based on groupId and agentId. - Introduced `contentMetadataMap` to store metadata for each content part, allowing efficient parallel content detection. - Updated `Message` and `ContentRender` components to utilize the new metadata structure for rendering. - Modified `useStepHandler` to manage content indices and metadata during message processing. - Enhanced `IJobStore` interface and its implementations to support storing and retrieving content metadata. - Updated data schemas to include `contentMetadataMap` for messages, enabling multi-agent and parallel execution scenarios. * refactor: update @librechat/agents dependency to version 3.0.56 * refactor: remove unused EPHEMERAL_AGENT_ID constant and simplify agent ID check * refactor: enhance multi-agent message processing and primary agent determination * refactor: implement branch message functionality for parallel responses * refactor: integrate added conversation retrieval into message editing and regeneration processes * refactor: remove unused isCard and isMultiMessage props from MessageRender and ContentRender components * refactor: update @librechat/agents dependency to version 3.0.60 * refactor: replace usage of EPHEMERAL_AGENT_ID constant with isEphemeralAgentId function for improved clarity and consistency * refactor: standardize agent ID format in tests for consistency * chore: move addedConvo property to the correct position in payload construction * refactor: rename agent_id values in loadAgent tests for clarity * chore: reorder props in ContentParts component for improved readability * refactor: rename variable 'content' to 'result' for clarity in RedisJobStore tests * refactor: streamline useMessageActions by removing duplicate handleFeedback assignment * chore: revert placeholder rendering logic MessageRender and ContentRender components to original * refactor: implement useContentMetadata hook for optimized content metadata handling * refactor: remove contentMetadataMap and related logic from the codebase and revert back to agentId/groupId in content parts - Eliminated contentMetadataMap from various components and services, simplifying the handling of message content. - Updated functions to directly access agentId and groupId from content parts instead of relying on a separate metadata map. - Adjusted related hooks and components to reflect the removal of contentMetadataMap, ensuring consistent handling of message content. - Updated tests and documentation to align with the new structure of message content handling. * refactor: remove logging from groupParallelContent function to clean up output * refactor: remove model parameter from TBranchMessageRequest type for simplification * refactor: enhance branch message creation by stripping metadata for standalone content * chore: streamline branch message creation by simplifying content filtering and removing unnecessary metadata checks * refactor: include attachments in branch message creation for improved content handling * refactor: streamline agent content processing by consolidating primary agent identification and filtering logic * refactor: simplify multi-agent message processing by creating a dedicated mapping method and enhancing content filtering * refactor: remove unused parameter from loadEphemeralAgent function for cleaner code * refactor: update groupId handling in metadata to only set when provided by the server
2025-12-25 01:43:54 -05:00
if (isEphemeralAgentId(agentCustomId)) {
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
return null;
}
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
return getAgent({ id: agentCustomId });
};
/**
* Creates a `canAccessResource` middleware for the given agent ID
* and chains to the provided continuation on success.
*
* @param {string} agentId - The agent's custom string ID (e.g., "agent_abc123")
* @param {number} requiredPermission - Permission bit(s) required
* @param {import('express').Request} req
* @param {import('express').Response} res - Written on deny; continuation called on allow
* @param {Function} continuation - Called when the permission check passes
* @returns {Promise<void>}
*/
const checkAgentResourceAccess = (agentId, requiredPermission, req, res, continuation) => {
const middleware = canAccessResource({
resourceType: ResourceType.AGENT,
requiredPermission,
resourceIdParam: 'agent_id',
idResolver: () => resolveAgentIdFromBody(agentId),
});
const tempReq = {
...req,
params: { ...req.params, agent_id: agentId },
};
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
return middleware(tempReq, res, continuation);
};
/**
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
* Middleware factory that validates MULTI_CONVO:USE role permission and, when
* addedConvo.agent_id is a non-ephemeral agent, the same resource-level permission
* required for the primary agent (`requiredPermission`). Caches the resolved agent
* document on `req.resolvedAddedAgent` to avoid a duplicate DB fetch in `loadAddedAgent`.
*
* @param {number} requiredPermission - Permission bit(s) to check on the added agent resource
* @returns {(req: import('express').Request, res: import('express').Response, next: Function) => Promise<void>}
*/
const checkAddedConvoAccess = (requiredPermission) => async (req, res, next) => {
const addedConvo = req.body?.addedConvo;
if (!addedConvo || typeof addedConvo !== 'object' || Array.isArray(addedConvo)) {
return next();
}
try {
if (!req.user?.role) {
return res.status(403).json({
error: 'Forbidden',
message: 'Insufficient permissions for multi-conversation',
});
}
if (req.user.role !== SystemRoles.ADMIN) {
const role = await getRoleByName(req.user.role);
const hasMultiConvo = role?.permissions?.[PermissionTypes.MULTI_CONVO]?.[Permissions.USE];
if (!hasMultiConvo) {
return res.status(403).json({
error: 'Forbidden',
message: 'Multi-conversation feature is not enabled',
});
}
}
const addedAgentId = addedConvo.agent_id;
if (!addedAgentId || typeof addedAgentId !== 'string' || isEphemeralAgentId(addedAgentId)) {
return next();
}
if (req.user.role === SystemRoles.ADMIN) {
return next();
}
const agent = await resolveAgentIdFromBody(addedAgentId);
if (!agent) {
return res.status(404).json({
error: 'Not Found',
message: `${ResourceType.AGENT} not found`,
});
}
const hasPermission = await checkPermission({
userId: req.user.id,
role: req.user.role,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
requiredPermission,
});
if (!hasPermission) {
return res.status(403).json({
error: 'Forbidden',
message: `Insufficient permissions to access this ${ResourceType.AGENT}`,
});
}
req.resolvedAddedAgent = agent;
return next();
} catch (error) {
logger.error('Failed to validate addedConvo access permissions', error);
return res.status(500).json({
error: 'Internal Server Error',
message: 'Failed to validate addedConvo access permissions',
});
}
};
/**
* Middleware factory that checks agent access permissions from request body.
* Validates both the primary agent_id and, when present, addedConvo.agent_id
* (which also requires MULTI_CONVO:USE role permission).
*
* @param {Object} options - Configuration options
* @param {number} options.requiredPermission - The permission bit required (1=view, 2=edit, 4=delete, 8=share)
* @returns {Function} Express middleware function
*
* @example
* router.post('/chat',
* canAccessAgentFromBody({ requiredPermission: PermissionBits.VIEW }),
* buildEndpointOption,
* chatController
* );
*/
const canAccessAgentFromBody = (options) => {
const { requiredPermission } = options;
if (!requiredPermission || typeof requiredPermission !== 'number') {
throw new Error('canAccessAgentFromBody: requiredPermission is required and must be a number');
}
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
const addedConvoMiddleware = checkAddedConvoAccess(requiredPermission);
return async (req, res, next) => {
try {
const { endpoint, agent_id } = req.body;
let agentId = agent_id;
if (!isAgentsEndpoint(endpoint)) {
agentId = Constants.EPHEMERAL_AGENT_ID;
}
if (!agentId) {
return res.status(400).json({
error: 'Bad Request',
message: 'agent_id is required in request body',
});
}
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
const afterPrimaryCheck = () => addedConvoMiddleware(req, res, next);
⏸ refactor: Improve UX for Parallel Streams (Multi-Convo) (#11096) * 🌊 feat: Implement multi-conversation feature with added conversation context and payload adjustments * refactor: Replace isSubmittingFamily with isSubmitting across message components for consistency * feat: Add loadAddedAgent and processAddedConvo for multi-conversation agent execution * refactor: Update ContentRender usage to conditionally render PlaceholderRow based on isLast and isSubmitting * WIP: first pass, sibling index * feat: Enhance multi-conversation support with agent tracking and display improvements * refactor: Introduce isEphemeralAgentId utility and update related logic for agent handling * refactor: Implement createDualMessageContent utility for sibling message display and enhance useStepHandler for added conversations * refactor: duplicate tools for added agent if ephemeral and primary agent is also ephemeral * chore: remove deprecated multimessage rendering * refactor: enhance dual message content creation and agent handling for parallel rendering * refactor: streamline message rendering and submission handling by removing unused state and optimizing conditional logic * refactor: adjust content handling in parallel mode to utilize existing content for improved agent display * refactor: update @librechat/agents dependency to version 3.0.53 * refactor: update @langchain/core and @librechat/agents dependencies to latest versions * refactor: remove deprecated @langchain/core dependency from package.json * chore: remove unused SearchToolConfig and GetSourcesParams types from web.ts * refactor: remove unused message properties from Message component * refactor: enhance parallel content handling with groupId support in ContentParts and useStepHandler * refactor: implement parallel content styling in Message, MessageRender, and ContentRender components. use explicit model name * refactor: improve agent ID handling in createDualMessageContent for dual message display * refactor: simplify title generation in AddedConvo by removing unused sender and preset logic * refactor: replace string interpolation with cn utility for className in HoverButtons component * refactor: enhance agent ID handling by adding suffix management for parallel agents and updating related components * refactor: enhance column ordering in ContentParts by sorting agents with suffix management * refactor: update @librechat/agents dependency to version 3.0.55 * feat: implement parallel content rendering with metadata support - Added `ParallelContentRenderer` and `ParallelColumns` components for rendering messages in parallel based on groupId and agentId. - Introduced `contentMetadataMap` to store metadata for each content part, allowing efficient parallel content detection. - Updated `Message` and `ContentRender` components to utilize the new metadata structure for rendering. - Modified `useStepHandler` to manage content indices and metadata during message processing. - Enhanced `IJobStore` interface and its implementations to support storing and retrieving content metadata. - Updated data schemas to include `contentMetadataMap` for messages, enabling multi-agent and parallel execution scenarios. * refactor: update @librechat/agents dependency to version 3.0.56 * refactor: remove unused EPHEMERAL_AGENT_ID constant and simplify agent ID check * refactor: enhance multi-agent message processing and primary agent determination * refactor: implement branch message functionality for parallel responses * refactor: integrate added conversation retrieval into message editing and regeneration processes * refactor: remove unused isCard and isMultiMessage props from MessageRender and ContentRender components * refactor: update @librechat/agents dependency to version 3.0.60 * refactor: replace usage of EPHEMERAL_AGENT_ID constant with isEphemeralAgentId function for improved clarity and consistency * refactor: standardize agent ID format in tests for consistency * chore: move addedConvo property to the correct position in payload construction * refactor: rename agent_id values in loadAgent tests for clarity * chore: reorder props in ContentParts component for improved readability * refactor: rename variable 'content' to 'result' for clarity in RedisJobStore tests * refactor: streamline useMessageActions by removing duplicate handleFeedback assignment * chore: revert placeholder rendering logic MessageRender and ContentRender components to original * refactor: implement useContentMetadata hook for optimized content metadata handling * refactor: remove contentMetadataMap and related logic from the codebase and revert back to agentId/groupId in content parts - Eliminated contentMetadataMap from various components and services, simplifying the handling of message content. - Updated functions to directly access agentId and groupId from content parts instead of relying on a separate metadata map. - Adjusted related hooks and components to reflect the removal of contentMetadataMap, ensuring consistent handling of message content. - Updated tests and documentation to align with the new structure of message content handling. * refactor: remove logging from groupParallelContent function to clean up output * refactor: remove model parameter from TBranchMessageRequest type for simplification * refactor: enhance branch message creation by stripping metadata for standalone content * chore: streamline branch message creation by simplifying content filtering and removing unnecessary metadata checks * refactor: include attachments in branch message creation for improved content handling * refactor: streamline agent content processing by consolidating primary agent identification and filtering logic * refactor: simplify multi-agent message processing by creating a dedicated mapping method and enhancing content filtering * refactor: remove unused parameter from loadEphemeralAgent function for cleaner code * refactor: update groupId handling in metadata to only set when provided by the server
2025-12-25 01:43:54 -05:00
if (isEphemeralAgentId(agentId)) {
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
return afterPrimaryCheck();
}
🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo (#12243) * 🛡️ fix: Enforce MULTI_CONVO and agent ACL checks on addedConvo addedConvo.agent_id was passed through to loadAddedAgent without any permission check, enabling an authenticated user to load and execute another user's private agent via the parallel multi-convo feature. The middleware now chains a checkAddedConvoAccess gate after the primary agent check: when req.body.addedConvo is present it verifies the user has MULTI_CONVO:USE role permission, and when the addedConvo agent_id is a real (non-ephemeral) agent it runs the same canAccessResource ACL check used for the primary agent. * refactor: Harden addedConvo middleware and avoid duplicate agent fetch - Convert checkAddedConvoAccess to curried factory matching Express middleware signature: (requiredPermission) => (req, res, next) - Call checkPermission directly for the addedConvo agent instead of routing through canAccessResource's tempReq pattern; this avoids orphaning the resolved agent document and enables caching it on req.resolvedAddedAgent for downstream loadAddedAgent - Update loadAddedAgent to use req.resolvedAddedAgent when available, eliminating a duplicate getAgent DB call per chat request - Validate addedConvo is a plain object and agent_id is a string before passing to isEphemeralAgentId (prevents TypeError on object injection, returns 400-equivalent early exit instead of 500) - Fix JSDoc: "VIEW access" → "same permission as primary agent", add @param/@returns to helpers, restore @example on factory - Fix redundant return await in resolveAgentIdFromBody * test: Add canAccessAgentFromBody spec covering IDOR fix 26 integration tests using MongoMemoryServer with real models, ACL entries, and PermissionService — no mocks for core logic. Covered paths: - Factory validation (requiredPermission type check) - Primary agent: missing agent_id, ephemeral, non-agents endpoint - addedConvo absent / invalid shape (string, array, object injection) - MULTI_CONVO:USE gate: denied, missing role, ADMIN bypass - Agent resource ACL: no ACL → 403, insufficient bits → 403, nonexistent agent → 404, valid ACL → next + cached on req - End-to-end: both real agents, primary denied short-circuits, ephemeral primary + real addedConvo
2026-03-15 17:12:45 -04:00
return checkAgentResourceAccess(agentId, requiredPermission, req, res, afterPrimaryCheck);
} catch (error) {
logger.error('Failed to validate agent access permissions', error);
return res.status(500).json({
error: 'Internal Server Error',
message: 'Failed to validate agent access permissions',
});
}
};
};
module.exports = {
canAccessAgentFromBody,
};