Raised on LibreChat-AI#16433: LibreChat-AI#16433 (comment)
PATCH /api/admin/config/:principalType/:principalId/fields validates the written fields on top of the principal's stored override, then applies them with independent $set operations and no version predicate (packages/api/src/admin/config.ts, patchConfigFields in packages/data-schemas/src/methods/config.ts).
What happens: two concurrent patches that update related fields both validate against the same old stored document and both succeed. For example, from a valid CloudFront override, one request sets requireSignedAccess: true while another sets imageSigning: "none"; the combined stored document is invalid, and merge-time validation silently drops one of the settings.
Expected: field validation and the write are atomic, either with an optimistic configVersion predicate on the patch (retry or 409 on conflict) or a read-validate-update transaction, so a patch never succeeds against a stored document other than the one it was validated on.
Raised on LibreChat-AI#16433: LibreChat-AI#16433 (comment)
PATCH /api/admin/config/:principalType/:principalId/fieldsvalidates the written fields on top of the principal's stored override, then applies them with independent$setoperations and no version predicate (packages/api/src/admin/config.ts,patchConfigFieldsin packages/data-schemas/src/methods/config.ts).What happens: two concurrent patches that update related fields both validate against the same old stored document and both succeed. For example, from a valid CloudFront override, one request sets
requireSignedAccess: truewhile another setsimageSigning: "none"; the combined stored document is invalid, and merge-time validation silently drops one of the settings.Expected: field validation and the write are atomic, either with an optimistic
configVersionpredicate on the patch (retry or 409 on conflict) or a read-validate-update transaction, so a patch never succeeds against a stored document other than the one it was validated on.