Fix CVE-2026-53739 (CSRF) & CVE-2026-53740 (XSS)#508
Merged
Conversation
0d4837f to
0d240f3
Compare
Coverage Report for CI Build 27382839654Coverage increased (+0.07%) to 60.272%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
feb4bd1 to
2b65ddc
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Addresses two reported security vulnerabilities in Yoast Duplicate Post by hardening the admin-notice dismissal flow against CSRF and escaping user-controlled values in the Classic Editor scheduled-republish notice to prevent stored XSS.
Changes:
- Adds nonce + capability checks to the
duplicate_post_dismiss_noticeAJAX handler and passes a nonce from the notice UI. - Escapes permalink and title in the Classic Editor “scheduled to replace” notice.
- Adds/updates unit tests covering the new CSRF protections and XSS escaping behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
admin-functions.php |
Adds nonce generation to the notice UI and enforces manage_options + nonce verification in the dismiss handler. |
src/ui/classic-editor.php |
Escapes permalink (esc_url) and title (esc_html) before interpolating into scheduled-republish notice HTML. |
tests/WP/Admin_Functions_Test.php |
Adds WP integration tests validating dismiss behavior for valid/invalid nonce and insufficient capability. |
tests/Unit/UI/Classic_Editor_Test.php |
Updates existing tests to stub escaping and adds a regression test for malicious titles in scheduled notice output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add a nonce to the dismiss-notice AJAX request and verify both the nonce and the manage_options capability in duplicate_post_dismiss_notice() before updating the site option. Covered by integration tests asserting the option only changes for an authorized user with a valid nonce.
…26-53740) Wrap the permalink with esc_url() and the post title with esc_html() before injecting them into the Classic Editor post-updated notice, preventing stored XSS via a malicious Rewrite & Republish copy title. Covered by a test asserting a hostile title is rendered as inert text.
2b65ddc to
ea9fbc2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Two vulnerabilities were disclosed against Yoast Duplicate Post (all versions through 4.6):
wp_admin_notice()runs admin notices throughwp_kses_post()(WP 6.4+), so the payload renders inert and script execution is only reachable on WordPress older than 6.4. The values are now escaped at the source so the plugin no longer relies on that core behavior.Summary
This PR can be summarized in the following changelog entry:
manage_optionscapability.Relevant technical choices:
manage_optionscapability — the same capability already required to see the notice (duplicate_post_show_update_notice()) — plus a nonce that is generated withwp_create_nonce(), sent with the existing AJAX request, and verified withcheck_ajax_referer().esc_url()and the title inesc_html(). The surrounding sentence already goes throughesc_html__(), so only the interpolated link needed escaping.wp_kses_post()viawp_admin_notice(), WP 6.4+), so the notice is not exploitable on the supported WP range (6.8+). The escaping also covers older cores that echo the message raw.Test instructions
Test instructions for the acceptance test before the PR gets merged
This PR can be acceptance tested by following these steps:
Stored XSS (CVE-2026-53740)
Core (WP 6.4+) already strips
<script>and event handlers from admin notices, so on a supported install this is verified by confirming the copy title is rendered as escaped text instead of being interpreted as HTML.<img src=x onerror=alert(1)>and schedule it for a future date.<img>element renders. (No alert fires even before the fix: WordPress core strips theonerrorhandler at output.)<img src=x onerror=alert(1)>) and no element renders.CSRF (CVE-2026-53739)
This verifies the notice can only be dismissed by a request that carries a valid nonce (what a normal click sends), and not by a forged request that lacks one.
wp eval "update_site_option('duplicate_post_show_notice', 1);", then reload.)nonce: 'invalid'to the object.) The logged response should be0— the request was rejected.Relevant test scenarios
Test instructions for QA when the code is in the RC
Impact check
This PR affects the following parts of the plugin, which may require extra testing:
duplicate_post_dismiss_notice()AJAX handler inadmin-functions.php).src/ui/classic-editor.php).UI changes
Documentation
Quality assurance
Innovation
innovationlabel and noted the work hours.Fixes CVE-2026-53739 and CVE-2026-53740.