Page MenuHomePhabricator

Concurrent calls to REST false positive endpoint can increment ctd_count incorrectly
Open, Needs TriagePublicBUG REPORT

Description

What is the problem?

If I make multiple concurrent requests to the /wikimediaantiabuse/v0/[un]mark/revision/<revid>/<tag>/false-positive endpoint, I can make the ctd_count column incorrect in the change_tag_def table. For instance, I can see the count incremented twice even though only one revision has been newly tagged.

Steps to reproduce problem
  1. Install WikimediaAntiAbuse extension
  2. Add $wgWikimediaAntiAbuseEnablePersonalInfoTag = true; to your LocalSettings.php
  3. Find a revision on your local wiki and record its revision ID
  4. From the root of your wiki: php maintenance/run.php --wiki <wiki> applyChangeTag --tag mw-private-personal-info --revisions <revid>
  5. Connect to your local database and run: SELECT * FROM change_tag_def WHERE ctd_name LIKE "mw-private-personal-info%";
    1. Make a note of the ctd_count of mw-private-personal-info and mw-private-personal-info-false-positive rows (the latter may not exist yet)
  6. Download P95939 and save it as false_positive_concurrent.py
  7. On your local wiki, give two users (<user1> and <user2>) suppressor rights
  8. Run: python3 false_positive_concurrent.py --url <wiki url> -r <revid> --user1 <user1> --password1 <password> --user2 <user2> --password2 <password> (you may need to install python3-multiprocess)
  9. Run again: SELECT * FROM change_tag_def WHERE ctd_name LIKE "mw-private-personal-info%";

Expected behaviour: The ctd_count for the row mw-private-personal-info-false-positive should have been incremented once.
Observed behaviour: It is incremented twice.

If you run python3 false_positive_concurrent.py --url <wiki url> -r <revid> --user1 <user1> --password1 <password> --user2 <user2> --password2 <password> -t unmark you will see the row mw-private-personal-info incremented twice as well.

Environment

Wiki(s): local docker WikimediaAntiAbuse – (af8bf6a) 07:58, 6 August 2026.

Event Timeline

Dreamy_Jazz subscribed.

The bug is in MediaWiki core. Specifically ChangeTagsStore::updateTags does the increment such that the count is updated at the end of the transaction. However, nothing is stopping two calls executing at the same time where one has it's update ignored (because the insert is done by ignoring any conflicts)

This does not happen for removing a tag, as the update is only done if the delete actually deleted a row. We should probably copy the same code for this

Change #1328281 had a related patch set uploaded (by Dreamy Jazz; author: Dreamy Jazz):

[mediawiki/core@master] ChangeTagsStore: Only increment tag count if insert updated table

https://gerrit.wikimedia.org/r/1328281

Change #1328281 merged by jenkins-bot:

[mediawiki/core@master] ChangeTagsStore: Only increment tag count if insert updated table

https://gerrit.wikimedia.org/r/1328281

I cannot reproduce the bug, even with three concurrent requests.

Change #1330447 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/core@master] ChangeTagsStore: Report only the tags which updateTags inserted

https://gerrit.wikimedia.org/r/1330447

Change #1330464 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/FileImporter@master] tests: Remove assertion about which tags a publish adds

https://gerrit.wikimedia.org/r/1330464