From 918e9527c53c4e18be7f383a874c136537693e82 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 15 Jul 2026 12:50:32 +0200 Subject: [PATCH] wip --- .../view/src/Attributes/ExpressionAttribute.php | 6 +++++- tests/Integration/View/TempestViewRendererTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/view/src/Attributes/ExpressionAttribute.php b/packages/view/src/Attributes/ExpressionAttribute.php index 0fd8209d8..67b9acc8d 100644 --- a/packages/view/src/Attributes/ExpressionAttribute.php +++ b/packages/view/src/Attributes/ExpressionAttribute.php @@ -70,7 +70,11 @@ public static function render(string $name, mixed $value): string return ''; } - $resolvedValue = self::resolveValue($value); + $resolvedValue = htmlspecialchars( + string: self::resolveValue($value), + flags: ENT_QUOTES | ENT_SUBSTITUTE, + encoding: 'UTF-8', + ); if ($resolvedValue === '') { return ''; diff --git a/tests/Integration/View/TempestViewRendererTest.php b/tests/Integration/View/TempestViewRendererTest.php index c0d5b6e5f..a162e8885 100644 --- a/tests/Integration/View/TempestViewRendererTest.php +++ b/tests/Integration/View/TempestViewRendererTest.php @@ -1000,4 +1000,17 @@ public function test_whitespace_with_blank_lines_between_inline_elements_is_pres Test

'), ); } + + public function test_expressions_attributes_are_escaped(): void + { + $html = $this->view->render(view( + 'click', + v: 'x" onmouseover="alert(document.cookie)', + )); + + $this->assertSnippetsMatch( + 'click', + $html, + ); + } }