Skip to content

Commit f65aba1

Browse files
maxfentonezyang
authored andcommitted
fix: reject angle brackets in body rather than partial stripping
The previous sanitizeBody approach (strip <>"' then strip script/alert/javascript) left residual content after multi-pass stripping. For example: <script>alert("xss")</script> → after step 1: scriptalert(xss)/script → after step 2: (xss)/ ← fails test expectation of empty string Decode URL encoding first to catch encoded payloads, then reject the entire body value if angle brackets are present (the primary HTML injection vector), rather than attempting partial character stripping that can be bypassed. Also re-encode the output so decoded bodies (e.g. Hello%20World) round-trip correctly through the URL attribute context. Add missing tests for: - sms:988 (no body — short code used by Crisis Text Line / 988 Lifeline) - sms:741741?body=SEIZE (RFC 5724 ?body= input normalised to &body= output) - sms:741741&body=SEIZE (short code with body round-trip)
1 parent 0bd3de9 commit f65aba1

2 files changed

Lines changed: 38 additions & 5 deletions

File tree

library/HTMLPurifier/URIScheme/sms.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,19 @@ public function doValidate(&$uri, $config, $context)
109109
*/
110110
private function sanitizeBody($body)
111111
{
112-
// Remove potentially dangerous characters
113-
$sanitized = preg_replace('/[<>"\']/', '', $body);
114-
// Remove any remaining script-like content
115-
$sanitized = preg_replace('/script|alert|javascript/i', '', $sanitized);
116-
return $sanitized;
112+
// Decode URL encoding first so encoded payloads are caught
113+
$decoded = rawurldecode($body);
114+
115+
// Angle brackets are the primary HTML injection vector — reject the
116+
// entire body if they appear rather than trying to strip them partially
117+
if (strpos($decoded, '<') !== false || strpos($decoded, '>') !== false) {
118+
return '';
119+
}
120+
121+
// Strip quote characters that could break HTML attribute context
122+
$sanitized = preg_replace('/[\'"]/', '', $decoded);
123+
124+
// Re-encode so the value is safe for embedding in a URL attribute
125+
return rawurlencode($sanitized);
117126
}
118127
}

tests/HTMLPurifier/URISchemeTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,30 @@ public function test_sms_strip_invalid_query_params()
300300
);
301301
}
302302

303+
public function test_sms_no_body()
304+
{
305+
$this->assertValidation(
306+
'sms:988'
307+
);
308+
}
309+
310+
public function test_sms_standard_query_format()
311+
{
312+
// RFC 5724 uses ?body= but &body= is the common web format;
313+
// the implementation normalises both to the &body= output form
314+
$this->assertValidation(
315+
'sms:741741?body=SEIZE',
316+
'sms:741741&body=SEIZE'
317+
);
318+
}
319+
320+
public function test_sms_short_code()
321+
{
322+
$this->assertValidation(
323+
'sms:741741&body=SEIZE'
324+
);
325+
}
326+
303327
public function test_data_png()
304328
{
305329
$this->assertValidation(

0 commit comments

Comments
 (0)