From ddafc0f7f6064f2c7c068eb8fefbe5d8a52a632a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 23 Aug 2026 13:38:50 -0400 Subject: [PATCH 1/3] Substitute invalid UTF-8 in JSON error renderer output json_encode() returns false for strings with invalid UTF-8 sequences, so exception messages or titles carrying raw binary data produced an empty response body under a JSON content type. Pass JSON_INVALID_UTF8_SUBSTITUTE so invalid sequences are replaced with the UTF-8 replacement character instead of discarding the whole payload. --- Slim/Error/Renderers/JsonErrorRenderer.php | 6 +++++- tests/Error/AbstractErrorRendererTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Slim/Error/Renderers/JsonErrorRenderer.php b/Slim/Error/Renderers/JsonErrorRenderer.php index 06085d2e5..4902c8a61 100644 --- a/Slim/Error/Renderers/JsonErrorRenderer.php +++ b/Slim/Error/Renderers/JsonErrorRenderer.php @@ -16,6 +16,7 @@ use function get_class; use function json_encode; +use const JSON_INVALID_UTF8_SUBSTITUTE; use const JSON_PRETTY_PRINT; use const JSON_UNESCAPED_SLASHES; @@ -35,7 +36,10 @@ public function __invoke(Throwable $exception, bool $displayErrorDetails): strin } while ($exception = $exception->getPrevious()); } - return (string) json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + return (string) json_encode( + $error, + JSON_INVALID_UTF8_SUBSTITUTE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES + ); } /** diff --git a/tests/Error/AbstractErrorRendererTest.php b/tests/Error/AbstractErrorRendererTest.php index f47fee4c8..a122d837d 100644 --- a/tests/Error/AbstractErrorRendererTest.php +++ b/tests/Error/AbstractErrorRendererTest.php @@ -163,6 +163,19 @@ public function testJSONErrorRendererDoesNotDisplayErrorDetails() $this->assertSame($output, json_encode(['message' => 'Slim Application Error'])); } + public function testJSONErrorRendererSubstitutesInvalidUtf8() + { + $exception = new Exception("Invalid \xB1\x31 UTF-8 sequence"); + + $renderer = new JsonErrorRenderer(); + $output = $renderer->__invoke($exception, false); + + $this->assertNotSame('', $output); + $decoded = json_decode($output, true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('message', $decoded); + } + public function testJSONErrorRendererDisplaysPreviousError() { $previousException = new Exception('Oh no!'); From f9ffaa925a7eab2e1ace79e28153a375d57839ca Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 25 Aug 2026 07:22:46 -0400 Subject: [PATCH 2/3] Prove JSON error renderer substitutes invalid UTF-8 The previous test invoked the renderer with displayErrorDetails=false, so only the title was encoded and the invalid exception message never reached json_encode. Assert the decoded exception message contains U+FFFD so the test fails if JSON_INVALID_UTF8_SUBSTITUTE is removed. --- tests/Error/AbstractErrorRendererTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Error/AbstractErrorRendererTest.php b/tests/Error/AbstractErrorRendererTest.php index a122d837d..aa9e1dfd3 100644 --- a/tests/Error/AbstractErrorRendererTest.php +++ b/tests/Error/AbstractErrorRendererTest.php @@ -168,12 +168,16 @@ public function testJSONErrorRendererSubstitutesInvalidUtf8() $exception = new Exception("Invalid \xB1\x31 UTF-8 sequence"); $renderer = new JsonErrorRenderer(); - $output = $renderer->__invoke($exception, false); + $output = $renderer->__invoke($exception, true); $this->assertNotSame('', $output); $decoded = json_decode($output, true); $this->assertIsArray($decoded); - $this->assertArrayHasKey('message', $decoded); + $this->assertSame('Slim Application Error', $decoded['message']); + $this->assertSame( + "Invalid \u{FFFD}1 UTF-8 sequence", + $decoded['exception'][0]['message'] + ); } public function testJSONErrorRendererDisplaysPreviousError() From 9b3c8d1a3ded95061f6a5d950d2c0d2cb302d048 Mon Sep 17 00:00:00 2001 From: Rob Allen Date: Wed, 26 Aug 2026 16:57:47 +0100 Subject: [PATCH 3/3] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4baed2f..4dc1e0f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Fixed + - Substitute invalid UTF-8 in JSON error renderer output (#811) ### Added