Commit 35019f9
Sync v1.9.1 into develop + clear dev-dependency CVEs (#765)
* Fix PHPStan errors and phpunit CVE on main
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).
* Fix abstract method fatal in test-class-security.php
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.
* v1.9.1 (#763)
* 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 `&` 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>
* Fix plain-text title test to pass on multisite
On multisite, editors lack the unfiltered_html capability, so core's kses
encodes the ampersand in the test title and the byte-for-byte assertion
fails. Grant the capability (via super admin on multisite) so the test
isolates our XSS sanitization rather than core's kses behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Grant unfiltered_html before switching user in title test
kses_init() runs on the set_current_user hook and decides whether to
attach the kses filters at switch time. The capability must be granted
before wp_set_current_user(), otherwise the filters are already attached
and the multisite assertion still sees the ampersand encoded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Bump composer/composer 2.9.2 -> 2.10.0 to clear dev-dependency CVEs
Resolves the Security check failure: composer/composer 2.9.2 (pulled in
transitively via wp-cli/wp-cli-bundle in require-dev) carried CVE-2026-40176,
CVE-2026-40261, and CVE-2026-45793. Targeted `composer update composer/composer
--with-dependencies`; composer.json (runtime deps) unchanged. `composer audit`
now reports no advisories.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Joost de Valk <joost@altha.nl>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent a15bf2d commit 35019f9
11 files changed
Lines changed: 628 additions & 157 deletions
File tree
- assets/js
- classes
- update
- utils
- tests/phpunit
- views/js-templates
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
472 | 472 | | |
473 | 473 | | |
474 | 474 | | |
| 475 | + | |
| 476 | + | |
475 | 477 | | |
476 | 478 | | |
477 | 479 | | |
478 | 480 | | |
479 | | - | |
| 481 | + | |
480 | 482 | | |
481 | 483 | | |
482 | 484 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
70 | 73 | | |
71 | 74 | | |
72 | 75 | | |
| |||
505 | 508 | | |
506 | 509 | | |
507 | 510 | | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
508 | 533 | | |
509 | 534 | | |
510 | 535 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
260 | 260 | | |
261 | 261 | | |
262 | 262 | | |
263 | | - | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
264 | 266 | | |
265 | | - | |
| 267 | + | |
266 | 268 | | |
267 | 269 | | |
268 | 270 | | |
| |||
294 | 296 | | |
295 | 297 | | |
296 | 298 | | |
297 | | - | |
| 299 | + | |
298 | 300 | | |
299 | 301 | | |
300 | 302 | | |
| |||
0 commit comments