WordPress.org

Make WordPress Core

Opened 14 months ago

Last modified 14 months ago

#44886 new defect (bug)

Race condition in REST API, can cause data loss

Reported by: rldk Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.9.8
Component: REST API Keywords:
Focuses: rest-api Cc:
PR Number:

Description

If, while a client is downloading a collection from the REST API, a
second client does something that should remove from that collection
a record which the first client has already downloaded, the REST API
will remove some *other* record from the first client’s collection in
order to make the total number of downloaded records be accurate.

For the demonstration below, the race condition is made repeatable by
having both clients pause at exactly the right (i.e. wrong!) moment.

Summary of the demonstration:

  1. The site holds “Important Post 1” through “Important Post 12”.
  2. Someone accidentally publishes “My test post”.
  3. An automated client begins downloading all posts (e.g. for backup, or syndication).
  4. Someone deletes “My test post”.
  5. The automated client finishes downloading.
  6. Later, when someone needs the downloaded dataset, “Important Post 3” is
    missing, just because someone deleted “My test post” during the download.

This bug was reported downstream at https://bugs.debian.org/898309.

To demonstrate:

(Files attached to this report are prefixed with “~/Downloads/” below.)

Installing and configuring the server software:

This isn’t meant to be secure; don’t expose it on a public IP address!

# cat /etc/issue.net
Debian GNU/Linux 9
# mkdir ~/wprestrace-server
# cd ~/wprestrace-server
# cp -a ~/Downloads/basic-auth.tar.gz .
# wget https://wordpress.org/wordpress-4.9.8.tar.gz
  [...]
# wget https://www.apachefriends.org/xampp-files/7.2.9/xampp-linux-x64-7.2.9-0-installer.run
  [...]
# chmod +x xampp-linux-x64-7.2.9-0-installer.run
# ./xampp-linux-x64-7.2.9-0-installer.run

(accept defaults, install, launch)
Manage Servers > MySQL Database > Start

# cd /opt/lampp/htdocs
# tar xpzf ~/wprestrace-server/wordpress-4.9.8.tar.gz
# mv wordpress wp
# tar xpzf ~/wprestrace-server/basic-auth.tar.gz -C wp/wp-content/plugins
# chown -R daemon:daemon wp
#

browse to http://localhost/phpmyadmin/
Databases
Database name: root_wp
Collation: utf8_unicode_ci
Create

browse to http://localhost/wp/
Continue
Let’s go!
Database Name: root_wp
Username: root
Password:
Submit
Run the installation
Site Title: tempsite
Username: username
Password: password
Install WordPress
Log In
Plugins > Installed Plugins > JSON Basic Authentication > Activate

Done installing and configuring the server software.

Installing and configuring the client software:

# mkdir ~/wprestrace-client
# cd ~/wprestrace-client
# cp -a ~/Downloads/WpRestRacePopulate.js .
# cp -a ~/Downloads/WpRestRaceDownloadAll.js .
# cp -a ~/Downloads/WpRestRaceTestPost.js .
# wget https://deb.nodesource.com/setup_8.x
  [...]
# chmod +x setup_8.x
# ./setup_8.x
  [...]
# apt-get install nodejs
  [...]
# node -v
v8.11.4
# npm install -g wpapi
+ wpapi@1.1.2
added 33 packages in 2.636s
#

Done installing and configuring the client software.

Reproducing the race condition:

# cd ~/wprestrace-client
# export NODE_PATH=$(npm root -g)
#
# node WpRestRacePopulate.js username password http://localhost/wp/wp-json
Created "Important Post 1".
Created "Important Post 2".
Created "Important Post 3".
Created "Important Post 4".
Created "Important Post 5".
Created "Important Post 6".
Created "Important Post 7".
Created "Important Post 8".
Created "Important Post 9".
Created "Important Post 10".
Created "Important Post 11".
Created "Important Post 12".
#

Open another terminal emulator.
When asked to press Enter below, don’t do it yet!

# cd ~/wprestrace-client
# export NODE_PATH=$(npm root -g)
#
# node WpRestRaceTestPost.js username password http://localhost/wp/wp-json
Created "My test post".  Press Enter to delete it.

Go back to the original terminal emulator.
When asked to press Enter below, don’t do it yet!

# node WpRestRaceDownloadAll.js username password http://localhost/wp/wp-json
Downloading all posts:
    Downloaded "My test post".
    Downloaded "Important Post 12".
    Downloaded "Important Post 11".
    Downloaded "Important Post 10".
    Downloaded "Important Post 9".
    Downloaded "Important Post 8".
    Downloaded "Important Post 7".
    Downloaded "Important Post 6".
    Downloaded "Important Post 5".
    Downloaded "Important Post 4".
Press Enter to continue.

Go back to the second terminal emulator, and press Enter.
The command and output (including what you already saw) are:

# node WpRestRaceTestPost.js username password http://localhost/wp/wp-json
Created "My test post".  Press Enter to delete it.
Deleted "My test post".
#

Go back to the original terminal emulator, and press Enter.
The command and output (including what you already saw) are:

# node WpRestRaceDownloadAll.js username password http://localhost/wp/wp-json
Downloading all posts:
    Downloaded "My test post".
    Downloaded "Important Post 12".
    Downloaded "Important Post 11".
    Downloaded "Important Post 10".
    Downloaded "Important Post 9".
    Downloaded "Important Post 8".
    Downloaded "Important Post 7".
    Downloaded "Important Post 6".
    Downloaded "Important Post 5".
    Downloaded "Important Post 4".
Press Enter to continue.
    Downloaded "Important Post 2".
    Downloaded "Important Post 1".
    Downloaded "Hello world!".
Finished downloading all posts:
    My test post
    Important Post 12
    Important Post 11
    Important Post 10
    Important Post 9
    Important Post 8
    Important Post 7
    Important Post 6
    Important Post 5
    Important Post 4
    Important Post 2
    Important Post 1
    Hello world!
End of listing.
#

The DownloadAll client thinks that it successfully downloaded all posts,
but it never received “Important Post 3”!

Attachments (4)

basic-auth.tar.gz (1.5 KB) - added by rldk 14 months ago.
WpRestRacePopulate.js (507 bytes) - added by rldk 14 months ago.
WpRestRaceDownloadAll.js (916 bytes) - added by rldk 14 months ago.
WpRestRaceTestPost.js (638 bytes) - added by rldk 14 months ago.

Download all attachments as: .zip

Change History (6)

@rldk
14 months ago

#1 @TimothyBlynJacobs
14 months ago

  • Severity changed from major to normal

#2 @adamsilverstein
14 months ago

Related, possible duplicate of #44568

Note: See TracTickets for help on using tickets.