#9312 closed defect (bug) (fixed)
Avatar AJAX responses use esc_url() instead of esc_url_raw(), breaking JavaScript URL handling
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 14.5.0 | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Media | Keywords: | has-patch |
| Cc: | emaralive |
Description
Several AJAX handlers in bp-core/bp-core-avatars.php use esc_url() to sanitize avatar URLs in JSON responses. This causes issues when JavaScript sets these URLs as image src attributes, because esc_url() converts & to & (HTML entity), which becomes malformed when used in JavaScript.
Steps to Reproduce
- Upload a profile avatar with crop parameters
- After cropping, inspect the avatar image element before page reload
- The src attribute contains
&instead of&, making query parameters invalid
Before reload (broken):
src="...jpg?w=450&crop=113px,112px,225px,225px&resize=150,150"
After reload (correct):
src="...jpg?w=450&crop=113px,112px,225px,225px&resize=150,150"
Root Cause
esc_url() is designed for HTML output and converts & to &. When returned in a JSON response and used by JavaScript, the HTML entity is treated as literal characters, breaking the URL.
Affected Code
bp-core/bp-core-avatars.php:
- Line 921 (
bp_avatar_ajax_delete) - Line 1421 (
bp_avatar_ajax_set - webcam) - Line 1485 (
bp_avatar_ajax_set - crop) - Line 2502 (
bp_avatar_ajax_recycle_previous_avatar)
Proposed Fix
Replace esc_url() with esc_url_raw() for all avatar URLs returned in AJAX/JSON responses. esc_url_raw() sanitizes without HTML entity encoding, which is correct for non-HTML contexts.
// Before 'avatar' => esc_url( bp_core_fetch_avatar( ... ) ), // After 'avatar' => esc_url_raw( bp_core_fetch_avatar( ... ) ),
Environment
- BuddyPress 14.4.0
- WordPress 6.7+
Attachments (2)
Change History (11)
@
5 weeks ago
Avatar instant preview/reload when querystring is incorrectly encoded - no crop or resizing.
@
5 weeks ago
Avatar instant preview when querystring is encoded correctly - crop and resize are applied
#3
@
5 weeks ago
Yes (screenshots of broken and fixed behaviour attached).
As you can see from the code examples, the AJAX-returned instant preview image is originally 450px wide, with a defined crop size and crop origin, which is then resized to be 150x150 per the default and expected layout. Since the querystring encoding is incorrect, and the querystring is ignored, the image shows up as the full 450x450 width (i.e. uncropped), which means the instant preview breaks the layout.
When the querystring encoding is correct, the fresh upload neatly replaces the existing 150x150px image.
This was experienced on a WordPress VIP site, which supports a system such that images can be manipulated (and cached) on the fly (hence the sizing being in the querystring args), but it would affect other hosts / applications than do something similar.
#4
@
5 weeks ago
- Milestone changed from Under Consideration to 14.5.0
Thanks. I'll do some more tests, but this is good. :)
#5
@
5 weeks ago
I do have a buddypress setup on a vip, local, instance but can't replicate it. :/ I'm familiar with VIP Proton CDN. But maybe I'm missing some plugin to hook the CDN locally.
My guess is that there are might be some code hooking into bp_core_fetch_avatar_url and changing the values to use query params instead. And our esc_url escaping is affecting that.
Which would make sense why this has not been an issue until now.
I'll create a patch. The change to esc_url_raw won't create an issue to everyone else.
This ticket was mentioned in PR #427 on buddypress/buddypress by renatonascalves.
4 weeks ago
#6
- Keywords has-patch added; needs-patch removed
Trac ticket: https://buddypress.trac.wordpress.org/ticket/9312
@GaryJ Other than the urls being wrong, is there any UI issue you see?
This change has been in the plugin for while, since https://buddypress.trac.wordpress.org/changeset/12338. So I'm looking for possible related issues this is causing, besides confirming any UI issue you can share.