From b09494310d14a81f935f172f55d3076cc3a91655 Mon Sep 17 00:00:00 2001
From: Cody Reichert
Date: Fri, 2 Oct 2026 21:55:56 -0500
Subject: [PATCH 1/2] Fix text sanitization in single listing error response
---
src/simply-rets-utils.php | 2 +-
src/tests/test-api-error-messages.php | 80 +++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 1 deletion(-)
create mode 100644 src/tests/test-api-error-messages.php
diff --git a/src/simply-rets-utils.php b/src/simply-rets-utils.php
index 50380a8..749ec9b 100644
--- a/src/simply-rets-utils.php
+++ b/src/simply-rets-utils.php
@@ -603,7 +603,7 @@ public static function noResultsMsg($response) {
if (array_key_exists("message", $response)) {
return (
'
'
- . $response['message']
+ . esc_html($response['message'])
. '
'
);
}
diff --git a/src/tests/test-api-error-messages.php b/src/tests/test-api-error-messages.php
new file mode 100644
index 0000000..76c5b18
--- /dev/null
+++ b/src/tests/test-api-error-messages.php
@@ -0,0 +1,80 @@
+' . $escaped_message . '
';
+
+ $this->assertSame($expected, SrMessages::noResultsMsg(array('message' => $message)));
+
+ // Exercise the single-listing error path used by the reported exploit.
+ $response = array(
+ 'lastUpdate' => null,
+ 'response' => (object)array('message' => $message)
+ );
+ $this->assertSame($expected, SimplyRetsRenderer::srResidentialDetailsGenerator($response));
+ }
+
+ public static function apiMessageProvider() {
+ return array(
+ 'reported SVG payload' => array(
+ 'No property found wih MLS ID "
',
+ '</strong></p><img src=x onerror="alert(1)">'
+ ),
+ 'encoded HTML entities' => array(
+ '<svg onload=alert(1)>',
+ '<svg onload=alert(1)>'
+ ),
+ 'ordinary numeric ID' => array(
+ 'No property found wih MLS ID "99999999"',
+ 'No property found wih MLS ID "99999999"'
+ ),
+ 'text with ampersands and apostrophes' => array(
+ "Listing isn't available & cannot be displayed.",
+ 'Listing isn't available & cannot be displayed.'
+ )
+ );
+ }
+
+ public function testObjectApiResponseIsEscaped() {
+ $this->assertSame(
+ '
<svg onload=alert(1)>
',
+ SrMessages::noResultsMsg((object)array('message' => '