Skip to content

Options, Meta APIs: Prevent delete_expired_transients() from deleting site transients across networks - #13288

Open
wprashed wants to merge 1 commit into
WordPress:trunkfrom
wprashed:fix/65969-delete-expired-transients-multinetwork
Open

Options, Meta APIs: Prevent delete_expired_transients() from deleting site transients across networks#13288
wprashed wants to merge 1 commit into
WordPress:trunkfrom
wprashed:fix/65969-delete-expired-transients-multinetwork

Conversation

@wprashed

Copy link
Copy Markdown

Ticket

Trac ticket: https://core.trac.wordpress.org/ticket/65969

Description

In multisite environments, site transients and their timeout entries are stored in the global wp_sitemeta table, separated by site_id (representing the network ID).

The multisite cleanup query in delete_expired_transients() previously joined the transient value row (a) and timeout row (b) purely by matching b.meta_key with a.meta_key:

DELETE a, b FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
WHERE a.meta_key LIKE %s
AND a.meta_key NOT LIKE %s
AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
AND b.meta_value < %d

Because b.site_id = a.site_id was not required, an expired site transient on one network would match an unexpired site transient with the same key on a different network and delete it from wp_sitemeta, leaving an orphaned timeout row behind on the victim network.

This PR adds AND b.site_id = a.site_id to ensure the cleanup is properly scoped within the same network.

Testing Instructions

  1. Run the multisite test suite for this method:
    phpunit -c tests/phpunit/multisite.xml --filter test_delete_expired_transients_does_not_cross_networks
  2. Verify all assertions pass.

Use of AI Tools

AI assistance: Yes
Tool(s): Google Antigravity
Model(s): Gemini
Used for: Analyzing the cross-network multi-table delete issue, writing the multisite unit test, and applying the network qualification join condition.

… site transients across networks

In multisite environments, site transients and their timeout entries are stored in the global `wp_sitemeta` table, separated by `site_id` (the network ID).

The DELETE query in `delete_expired_transients()` joined the transient value row (`a`) and the timeout row (`b`) solely by matching `b.meta_key` with `a.meta_key`, without verifying that both rows belong to the same network. As a result, an expired site transient on one network would delete an unexpired site transient with the same key on another network, leaving behind an orphaned timeout row.

This commit adds `AND b.site_id = a.site_id` to qualify the join in `delete_expired_transients()`, ensuring deletions only occur within the same network.

Props robbsie, adamgreenwell, wprashed.
Fixes #65969.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props wprashed.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant