Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling 'updateMany' without 'update' param leads to entire collection updated by the 'filter' param's data #15190

Closed
2 tasks done
eyalk-af opened this issue Jan 21, 2025 · 1 comment · Fixed by #15199
Closed
2 tasks done
Milestone

Comments

@eyalk-af
Copy link

eyalk-af commented Jan 21, 2025

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

6.11.3

Node.js version

15.14

MongoDB server version

4.4.10

Typescript version (if applicable)

4.3.5

Description

A severe, undocumented behavior: Model.updateMany is switching between filter and update params if update is missing.

The result is unpredicted and very destructive as mongoose updates ALL records of the collection with the filter parameter.

The bug is clearly stated (yet undocumented) in file query.js (line 4038)

    doc = conditions;
    conditions = undefined;

Important to note that MongoDB rejects calls to updateMany without an update parameter .

This is only a mongoose undocumented feature, thus a (severe) bug as it updates the database without discretion.

Steps to Reproduce

For a model named PersonModel, which represents a collection (Person) containing fields like color (a string)

Call this method:

PersonModel.updateMany({ color : 'red' }); // should not compile + throw runtime error

Expected Result:
A runtime error should be thrown stating that 'update' must have a value (exactly as MongoDB rejects this issue)

Actual Result:
All records in collection Person are updated with their color set to "red"

Expected Behavior

Mongoose should

  1. Throw an error if this updateMany is called an undefined update paramter
  2. Remove the optional mark (?) from parameter update in updateMany
  3. document this behavior
  4. It should never ever update the entire collection with the filter's data (!!)
@eyalk-af eyalk-af changed the title Calling 'updateMany' without 'update' param leads to entire collection updated by the 'filter' param Calling 'updateMany' without 'update' param leads to entire collection updated by the 'filter' param's data Jan 22, 2025
vkarpov15 added a commit that referenced this issue Jan 23, 2025
@vkarpov15
Copy link
Collaborator

Hi, I'm very sorry for the trouble! It looks like this behavior was better documented in older versions of Mongoose, but we removed the examples that indicated this behavior when we removed support for callbacks.

You're right that this behavior is risky. However, I don't think we can change this behavior throughout without a breaking change because changing the equivalent code in updateOne() causes test failures. AFAIK the original intent of this syntax was to support chaining like Person.find({ name: 'John' }).updateMany({ color: 'red' }), see #3221 for an example. However, we should likely not support this behavior in Model.updateMany(), which would mean we can still support chaining syntax without the potential updateMany(update) footgun.

vkarpov15 added a commit that referenced this issue Jan 24, 2025
fix(model): disallow `updateMany(update)` and fix TypeScript types re: `updateMany()`
@vkarpov15 vkarpov15 added this to the 8.10 milestone Jan 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants