<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][14155] branches/14.0/src: Replace `esc_url()` with `esc_url_raw()` for almost all avatar URLs returned in AJAX/JSON responses.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://buddypress.trac.wordpress.org/changeset/14155">14155</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://buddypress.trac.wordpress.org/changeset/14155","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>espellcaste</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2025-12-17 14:10:24 +0000 (Wed, 17 Dec 2025)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Replace `esc_url()` with `esc_url_raw()` for almost all avatar URLs returned in AJAX/JSON responses.
This change addresses an issue where a site modifies the url returned by `bp_core_fetch_avatar`, and those URLs are returned as image src attributes.
In the process of escaping the url, `esc_url` converts those attributes becoming malformed. `esc_url_raw()` sanitizes the url without HTML entity encoding, which is correct for non-HTML contexts.
Since BuddyPress DOES NOT return the image src attributes by default as part of the url, this change should have no impact to regular users. Unless the site is purposefully changing them (the use case here is an image CDN that returns the image [on demand] using the src attributes as image params in the avatar url).
Originally at <a href="http://buddypress.trac.wordpress.org/changeset/12338">[12338]</a>.
Props GaryJ.
See https://github.com/buddypress/buddypress/pull/427
See <a href="http://buddypress.trac.wordpress.org/ticket/9312">#9312</a> (14.0)</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branches140srcbpcorebpcoreavatarsphp">branches/14.0/src/bp-core/bp-core-avatars.php</a></li>
<li><a href="#branches140srcbptemplatesbpnouveauincludesmessagesajaxphp">branches/14.0/src/bp-templates/bp-nouveau/includes/messages/ajax.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branches140srcbpcorebpcoreavatarsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/14.0/src/bp-core/bp-core-avatars.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/14.0/src/bp-core/bp-core-avatars.php 2025-12-17 13:48:48 UTC (rev 14154)
+++ branches/14.0/src/bp-core/bp-core-avatars.php 2025-12-17 14:10:24 UTC (rev 14155)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -882,9 +882,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Ajax delete an avatar for a given object and item id.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.3.0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- *
- * @return string|null A JSON object containing success data if the avatar was deleted,
- * error message otherwise.
</del><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> function bp_avatar_ajax_delete() {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! bp_is_post_request() ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -918,7 +915,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $return = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw(
</ins><span class="cx" style="display: block; padding: 0 10px"> bp_core_fetch_avatar(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => $avatar_data['object'],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1418,7 +1415,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $return = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw(
</ins><span class="cx" style="display: block; padding: 0 10px"> bp_core_fetch_avatar(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => $avatar_data['object'],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1482,7 +1479,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $cropped_avatar ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $return = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw(
</ins><span class="cx" style="display: block; padding: 0 10px"> bp_core_fetch_avatar(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => $avatar_data['object'],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1776,7 +1773,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 1.0.0
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param int $user_id ID of the user whose avatar is being checked.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return bool True if the user has uploaded a local avatar. Otherwise false.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return bool True if the user has uploaded a local avatar. Otherwise, false.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> function bp_get_user_has_avatar( $user_id = 0 ) {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2067,8 +2064,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @param WP_Query|null $posts_query The main query object.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> function bp_core_avatar_reset_query( $posts_query = null ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $reset_w = false;
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Group's avatar edit screen.
</span><span class="cx" style="display: block; padding: 0 10px"> if ( bp_is_group_admin_page() ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $reset_w = bp_is_group_admin_screen( 'group-avatar' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2428,10 +2423,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Init recycle vars.
</span><span class="cx" style="display: block; padding: 0 10px"> $recycle_timestamp = bp_core_current_time( true, 'timestamp' );
</span><span class="cx" style="display: block; padding: 0 10px"> $recycle_errors = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $avatar_types = array(
- 'full' => '',
- 'thumb' => '',
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $avatar_types = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Use the found previous avatar.
</span><span class="cx" style="display: block; padding: 0 10px"> $avatar = $avatars[ $avatar_id ];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2517,7 +2509,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $return = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw(
</ins><span class="cx" style="display: block; padding: 0 10px"> bp_core_fetch_avatar(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => $object,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2615,13 +2607,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $avatar_types = array(
- 'full' => '',
- 'thumb' => '',
- );
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Use the found previous avatar.
</span><span class="cx" style="display: block; padding: 0 10px"> $avatar = $avatars[ $avatar_id ];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $avatar_types = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> $avatar_types['full'] = $avatar->path;
</span><span class="cx" style="display: block; padding: 0 10px"> $avatar_types['thumb'] = str_replace( $suffix, '-bpthumb', $avatar->path );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="branches140srcbptemplatesbpnouveauincludesmessagesajaxphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/14.0/src/bp-templates/bp-nouveau/includes/messages/ajax.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/14.0/src/bp-templates/bp-nouveau/includes/messages/ajax.php 2025-12-17 13:48:48 UTC (rev 14154)
+++ branches/14.0/src/bp-templates/bp-nouveau/includes/messages/ajax.php 2025-12-17 14:10:24 UTC (rev 14155)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -233,7 +233,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_id' => bp_get_the_thread_message_sender_id(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_name' => esc_html( bp_get_the_thread_message_sender_name() ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_link' => bp_get_the_thread_message_sender_link(),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'sender_avatar' => esc_url( bp_core_fetch_avatar( array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'sender_avatar' => esc_url_raw( bp_core_fetch_avatar( array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'item_id' => bp_get_the_thread_message_sender_id(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => 'user',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'thumb',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -342,7 +342,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'unread' => bp_message_thread_has_unread(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_name' => bp_core_get_user_displayname( $messages_template->thread->last_sender_id ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_link' => bp_core_get_userlink( $messages_template->thread->last_sender_id, false, true ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'sender_avatar' => esc_url( bp_core_fetch_avatar( array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'sender_avatar' => esc_url_raw( bp_core_fetch_avatar( array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'item_id' => $messages_template->thread->last_sender_id,
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => 'user',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'thumb',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -358,7 +358,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_array( $messages_template->thread->recipients ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $messages_template->thread->recipients as $recipient ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $threads->threads[ $i ]['recipients'][] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url( bp_core_fetch_avatar( array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw( bp_core_fetch_avatar( array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'item_id' => $recipient->user_id,
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => 'user',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'thumb',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -508,7 +508,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_array( $thread_template->thread->recipients ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $thread_template->thread->recipients as $recipient ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $thread->thread['recipients'][] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'avatar' => esc_url( bp_core_fetch_avatar( array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'avatar' => esc_url_raw( bp_core_fetch_avatar( array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'item_id' => $recipient->user_id,
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => 'user',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'thumb',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -533,7 +533,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_id' => bp_get_the_thread_message_sender_id(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_name' => esc_html( bp_get_the_thread_message_sender_name() ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'sender_link' => bp_get_the_thread_message_sender_link(),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'sender_avatar' => esc_url( bp_core_fetch_avatar( array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'sender_avatar' => esc_url_raw( bp_core_fetch_avatar( array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'item_id' => bp_get_the_thread_message_sender_id(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'object' => 'user',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'thumb',
</span></span></pre>
</div>
</div>
</body>
</html>