LibreChat/api/server/middleware
Danny Avila 8dc6d60750
🛡️ 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
..
accessResources
assistants
config
limiters
roles
spec
validate
abortMiddleware.js
abortMiddleware.spec.js
abortRun.js
buildEndpointOption.js
buildEndpointOption.spec.js
canDeleteAccount.js
checkBan.js
checkDomainAllowed.js
checkInviteUser.js
checkPeoplePickerAccess.js
checkPeoplePickerAccess.spec.js
checkSharePublicAccess.js
checkSharePublicAccess.spec.js
denyRequest.js
error.js
index.js
logHeaders.js
moderateText.js
noIndex.js
optionalJwtAuth.js
requireJwtAuth.js
requireLdapAuth.js
requireLocalAuth.js
setHeaders.js
uaParser.js
validateImageRequest.js
validateMessageReq.js
validateModel.js
validatePasswordReset.js
validateRegistration.js