Skip to content

Security: escape attacker-influenced data rendered in admin views (XSS)#1381

Open
vuckro wants to merge 2 commits into
Ultimate-Multisite:mainfrom
vuckro:security/admin-views-xss-escaping
Open

Security: escape attacker-influenced data rendered in admin views (XSS)#1381
vuckro wants to merge 2 commits into
Ultimate-Multisite:mainfrom
vuckro:security/admin-views-xss-escaping

Conversation

@vuckro

@vuckro vuckro commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Several network-admin views render untrusted data as HTML, allowing stored XSS
that fires in an admin's browser.

Changes

  • Event::interpolate_message() substituted payload values (customer display
    names, site titles/descriptions, …) into HTML message templates without
    escaping; the result is rendered with Vue v-html in the activity-stream
    widget. Escape each interpolated value with esc_html() while preserving the
    template's own markup.
  • views/events/widget-payload.php rendered the JSON payload dump with
    v-html; switched to v-text (it is preformatted debug text).
  • Template libraryshort_description / price_html are fetched from the
    remote marketplace API and rendered with v-html; sanitize them server-side
    with wp_kses_post() so injected script is stripped while formatting is kept.
  • Webhook list table column_name interpolated the webhook name/event/url
    into HTML and data-* attributes unescaped; apply esc_html() / esc_attr()
    / esc_url().

No functional change for non-malicious data.

Summary by CodeRabbit

  • Bug Fixes
    • Webhook names, URLs and action metadata properly escape special characters to prevent display issues.
    • Template library descriptions and price HTML are sanitized to preserve allowed markup while blocking unsafe content.
    • Event payload widget now renders payloads as plain text to avoid unintended HTML rendering.

…s (XSS)

Several network-admin views rendered untrusted data as HTML:

- Event::interpolate_message() substituted payload values (customer display
  names, site titles/descriptions, etc.) into HTML message templates without
  escaping; the result is rendered with Vue v-html in the activity-stream
  widget — a stored XSS. Escape each interpolated value with esc_html() while
  preserving the template's own markup.
- views/events/widget-payload.php rendered the JSON payload dump with v-html;
  switched to v-text (it is preformatted debug text).
- Template library: short_description / price_html come from the remote
  marketplace API and are rendered with v-html; sanitize them server-side with
  wp_kses_post() so injected script is stripped while formatting is kept.
- Webhook list table column_name interpolated the webhook name/event/url into
  HTML and data-* attributes unescaped; apply esc_html()/esc_attr()/esc_url().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d9809157-3f0b-4c41-9b72-90958e3872ab

📥 Commits

Reviewing files that changed from the base of the PR and between 7a09098 and d3be4b1.

📒 Files selected for processing (1)
  • inc/list-tables/class-webhook-list-table.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • inc/list-tables/class-webhook-list-table.php

📝 Walkthrough

Walkthrough

This PR hardens output escaping and sanitization across admin webhook listing, event message interpolation, template library HTML fields, and the event payload widget to prevent HTML injection and XSS.

Changes

Output Escaping & Sanitization

Layer / File(s) Summary
Webhook admin list table output escaping
inc/list-tables/class-webhook-list-table.php
The webhook name is escaped with esc_html(), the "Send Test" action's data-title, data-event, and data-object use esc_attr(), data-url uses esc_url(), the webhook URL display is esc_html()-escaped, and the event value is escaped before output.
Event message template payload escaping
inc/models/class-event.php
interpolate_message() now escapes each payload value (flattening arrays and escaping elements) and escapes the derived {{payload}}, {{model}}, and {{object_id}} placeholders before substitution.
Template library API data sanitization
inc/template-library/class-api-client.php
parse_template_data() sanitizes short_description and price_html with wp_kses_post() and adds comments noting these fields are rendered via Vue v-html.
Event widget payload plain-text rendering
views/events/widget-payload.php
The event widget <pre> switches from v-html="payload" to v-text="payload", rendering the payload as plain text.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I nibble at strings with careful care,
Escape the bits that snarl and tear,
Webhooks tidy, payloads plain,
Templates scrubbed, no hidden bane,
A rabbit hops—safe code everywhere.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the primary change: escaping attacker-influenced data in admin views to prevent XSS vulnerabilities. It accurately reflects the security-focused scope across webhook tables, event interpolation, template library, and payload widgets.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
inc/list-tables/class-webhook-list-table.php (1)

100-103: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Same XSS pattern in multiple column methods. Both column_webhook_url() and column_event() interpolate model data into HTML without escaping. Since this security PR already fixes column_name(), consider applying the same esc_html() treatment to these adjacent methods for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@inc/list-tables/class-webhook-list-table.php` around lines 100 - 103,
column_webhook_url() and column_event() are interpolating model data directly
into HTML causing an XSS risk; update both methods to escape output (use
esc_html() or equivalent) when outputting values (e.g., wrap the trimmed URL and
event string with esc_html()) following the same pattern used in column_name()
so the returned span contains escaped content rather than raw model values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@inc/list-tables/class-webhook-list-table.php`:
- Around line 100-103: column_webhook_url() and column_event() are interpolating
model data directly into HTML causing an XSS risk; update both methods to escape
output (use esc_html() or equivalent) when outputting values (e.g., wrap the
trimmed URL and event string with esc_html()) following the same pattern used in
column_name() so the returned span contains escaped content rather than raw
model values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b6745c40-1f6b-4e51-9cc1-eb8fdf9dd2f9

📥 Commits

Reviewing files that changed from the base of the PR and between 1310078 and 7a09098.

📒 Files selected for processing (4)
  • inc/list-tables/class-webhook-list-table.php
  • inc/models/class-event.php
  • inc/template-library/class-api-client.php
  • views/events/widget-payload.php

…w-up)

Apply the same esc_html() treatment to column_webhook_url() and column_event()
that column_name() received, so all webhook list-table columns escape model data
before output.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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