Skip to content

Resolve 1.10.0 release conflicts (merge main into develop) - #781

Merged
ilicfilip merged 5 commits into
developfrom
filip/resolve-695-conflicts
Sep 3, 2026
Merged

Resolve 1.10.0 release conflicts (merge main into develop)#781
ilicfilip merged 5 commits into
developfrom
filip/resolve-695-conflicts

Conversation

@ilicfilip

Copy link
Copy Markdown
Collaborator

Back-merges main into develop to clear the conflicts blocking the 1.10.0 release PR (#695).

All conflicts resolve to develop's side:

  • Version 1.10.0, stable tag 1.10.0
  • The = 1.10.0 = changelog block (the = 1.9.1 = entry is preserved below it)
  • The dead login-redirect removal (save_redirect_on_login stays removed)
  • The color-customizer deletion
  • The hardened orderby handling in class-suggested-tasks.php

The 1.9.1 XSS sanitization fix from main is retained.

Verified: lint clean, PHPStan clean, 404 PHPUnit tests pass on the merged result.

Once merged, #695 (develop → main) becomes conflict-free.

🤖 Generated with Claude Code

ilicfilip and others added 5 commits May 26, 2026 12:12
Brings main's static analysis and dependency security checks back to green:

- Static Analysis: clear 25 pre-existing PHPStan errors. Ports develop's
  typed @return on Date::get_periods()/get_range() (which also resolves the
  Chart modify() errors), takes develop's exact versions of class-page-settings,
  class-activity-scores, class-chart and class-update-140, converts the WP-core
  require_once ignores to the @phpstan-ignore-next-line form that suppresses
  under PHPStan 2.1.x, and adds inline ignores elsewhere.
- Security check: bump phpunit/phpunit 9.6.30 -> 9.6.34 in composer.lock to
  resolve CVE-2026-24765 (unsafe deserialization in PHPT code coverage).
The anonymous classes extending the abstract Tasks_Interactive did not
implement the abstract Tasks::should_add_task() method. phpunit 9.6.30
did not surface this, but 9.6.34 (the CVE-2026-24765 fix) does, causing
a fatal when the test class loads. Implement should_add_task() in all 8
anonymous task providers.
Fix PHPStan errors and phpunit CVE on main
* Sanitize and escape prpl_recommendations title

An authenticated Editor (or higher) could create a recommendation via
POST /wp/v2/prpl_recommendations with an HTML payload in the `title`
field (e.g. `<img src=x onerror=alert(1)>`). The dashboard JS template
(views/js-templates/suggested-task.html) renders `title.rendered` with
Underscore's unescaped `{{{ }}}` syntax, so the payload executed when an
admin loaded the dashboard.

Defense in depth:

- Input: add a `rest_pre_insert_prpl_recommendations` filter that strips
  tags from `post_title` on every REST insert/update, regardless of the
  user's `unfiltered_html` capability. Recommendation titles are plain
  text, so this neutralizes the payload at the source.
- Output (JS): route the two raw `{{{ }}}` title sinks through a new
  `prplSuggestedTask.sanitizeTitle()` helper, which inert-parses the
  value with DOMParser (no script/resource side effects) and re-escapes
  it, preserving legitimate entities like `&amp;` without double-encoding
  the server-side `esc_html`'d provider titles.
- Output (admin bar): the PRPL debug tool printed `post_title` unescaped
  into a `WP_Admin_Bar` node id (an HTML attribute) and title (rendered
  as raw HTML), firing the payload on every admin page in debug mode.
  Escape the title with `esc_html()`, use the post ID for the node id,
  and escape the activities node title too.
- Also switch `updateTaskTitle` to set `.textContent` instead of
  `.innerHTML` for the screen-reader label, closing a self-XSS sink.

Adds tests/phpunit/test-class-rest-recommendations-xss.php covering
Editor and Administrator payloads plus a plain-text regression check.

* Bump version to 1.9.1

* add migration script and revert JS title escaping

* add inline comment, cc @tacoverdo

* Delete recommendation when sanitized title is empty

A title that is pure markup strips to an empty string. wp_update_post()
rejects an update that would leave the title, content, and excerpt all
empty, so the malicious title was left in the DB. The plugin never stores
title-less recommendations, so delete such rows instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* update readme.txt

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…flicts

# Conflicts:
#	classes/admin/class-page-settings.php
#	classes/class-suggested-tasks.php
#	classes/utils/class-color-customizer.php
#	composer.lock
#	progress-planner.php
#	readme.txt
#	tests/phpunit/test-class-rest-recommendations-xss.php
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Test merged PR on Playground
Test this pull request on the Playground
or download the zip

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🔍 WordPress Plugin Check Report

⚠️ Status: Passed with warnings

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
10 0 10

⚠️ Warnings (10)

📁 classes/suggested-tasks/providers/class-content-review.php (4 warnings)
📍 Line 🔖 Check 💬 Message
232 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
377 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
381 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
388 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
📁 classes/suggested-tasks/data-collector/class-unpublished-content.php (1 warning)
📍 Line 🔖 Check 💬 Message
103 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
📁 classes/suggested-tasks/data-collector/class-terms-without-posts.php (1 warning)
📍 Line 🔖 Check 💬 Message
120 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_results()\n$query assigned unsafely at line 118.
📁 classes/suggested-tasks/data-collector/class-yoast-orphaned-content.php (1 warning)
📍 Line 🔖 Check 💬 Message
111 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_row()\n$query assigned unsafely at line 98.
📁 classes/suggested-tasks/data-collector/class-terms-without-description.php (1 warning)
📍 Line 🔖 Check 💬 Message
108 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_results()\n$query assigned unsafely at line 106.
📁 classes/activities/class-query.php (2 warnings)
📍 Line 🔖 Check 💬 Message
71 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $table_name used in $wpdb->query()\n$table_name assigned unsafely at line 58.
163 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $where_args used in $wpdb->get_results()\n$where_args assigned unsafely at line 153.

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

✅ Code Coverage Report

Metric Value
Total Coverage 32.28% 📉
Base Coverage 32.28%
Difference 📈 0.00%

⚠️ Coverage below recommended 40% threshold

🎉 Great job maintaining/improving code coverage!

ℹ️ About this report
  • All tests run in a single job with Xdebug coverage
  • Security tests excluded from coverage to prevent output issues
  • Coverage calculated from line coverage percentages

@ilicfilip
ilicfilip merged commit 39ff31d into develop Sep 3, 2026
21 checks passed
@ilicfilip
ilicfilip deleted the filip/resolve-695-conflicts branch September 3, 2026 09:23
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.

2 participants