Privacy: Compare personal data request expiry in UTC - #12713
Conversation
The scheduled cleanup resolved its expiry threshold as a relative date string, which WP_Date_Query evaluates in the site's timezone, and compared it against the local post_modified column. Since post_modified holds the local time that was in effect when the request was made, changing the site's timezone by more than the expiry window retroactively expired pending requests: a seconds-old request could be marked request-failed and have its confirmation key cleared, breaking the confirmation link that had already been emailed. Compare an absolute UTC threshold against post_modified_gmt instead, so the cleanup matches wp_validate_user_request_key() and is unaffected by later timezone changes. Follow-up to [62662]. Fixes #65731. See #44498.
|
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 Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
This PR updates the personal data request cleanup logic to evaluate expiry using a timezone-invariant UTC threshold against the post_modified_gmt column, preventing fresh pending requests from being retroactively expired after a site timezone change.
Changes:
- Updates
_wp_personal_data_cleanup_requests()to compare againstpost_modified_gmtusing an absolute UTC threshold. - Updates existing tests’ documentation to reflect the new expiry behavior rationale.
- Adds a regression test ensuring a large timezone change does not expire a newly-created request.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/wp-admin/includes/privacy-tools.php |
Switches cleanup expiry comparison to use an absolute UTC threshold against post_modified_gmt. |
tests/phpunit/tests/privacy/wpPersonalDataCleanupRequests.php |
Adjusts test commentary and adds regression coverage for timezone changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 'column' => 'post_modified_gmt', | ||
| 'before' => gmdate( 'Y-m-d H:i:s', time() - $expires ), | ||
| ), |
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Personal data request cleanup resolved its expiry threshold in the site's timezone and compared it against the local post_modified column, so changing the site timezone retroactively expired pending requests.
What the problem was:
_wp_personal_data_cleanup_requests()passed'before' => $expires . ' seconds ago'.WP_Date_Query::build_mysql_datetime()resolves relative strings viadate_create( $datetime, wp_timezone() ), so the threshold is a site-local wall clock.post_modifiedcolumn, butpost_modifiedstores the local time in effect when the request was created.request-failedand itspost_passwordcleared, so the confirmation link already emailed to the recipient returns "Invalid personal data request."What the fix does:
gmdate( 'Y-m-d H:i:s', time() - $expires ), against thepost_modified_gmtcolumn.Approach and why:
wp_validate_user_request_key(), which is the authoritative expiry check and already comparesmodified_timestamp(parsed frompost_modified_gmt) againsttime(). Cleanup and validation can no longer disagree.wp_get_comment_reply_link()(src/wp-includes/comment.php).Y-m-d H:i:sstrings pass throughbuild_mysql_datetime()unchanged under UTC, Pago Pago, Kiritimati and New York.Trac ticket: https://core.trac.wordpress.org/ticket/65731
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Ticket analysis, code implementation, and tests. All changes were reviewed and validated by me.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.