From 157c6d49e8ea873287750e51d4b437d70f2f062d Mon Sep 17 00:00:00 2001 From: Gregor Klevze Date: Sat, 25 Apr 2026 08:12:46 +0200 Subject: [PATCH] Sanitize browse categories HTML output --- resources/views/browse-categories.blade.php | 10 +++++--- tests/Unit/ContentSanitizerTest.php | 28 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/resources/views/browse-categories.blade.php b/resources/views/browse-categories.blade.php index 79450f8c..8432016e 100644 --- a/resources/views/browse-categories.blade.php +++ b/resources/views/browse-categories.blade.php @@ -7,6 +7,10 @@ @extends('layouts.nova') @section('content') + @php + $sanitizeHtml = fn (?string $value) => \App\Services\ContentSanitizer::sanitizeRenderedHtml($value ?? ''); + @endphp +

Browse Categories

@@ -24,7 +28,7 @@

{{ $ct->name }}

-

{!! $ct->description ?? '' !!}

+

{!! $sanitizeHtml($ct->description) !!}

@php $roots = $categoriesByType[$ct->slug] ?? $ct->rootCategories ?? collect(); @@ -37,7 +41,7 @@ @foreach ($roots as $category)
  • {{ $category->name }}

    -

    {!! $category->description !!}

    +

    {!! $sanitizeHtml($category->description) !!}

    diff --git a/tests/Unit/ContentSanitizerTest.php b/tests/Unit/ContentSanitizerTest.php index a9de15db..ca3ab073 100644 --- a/tests/Unit/ContentSanitizerTest.php +++ b/tests/Unit/ContentSanitizerTest.php @@ -77,6 +77,34 @@ test('render adds rel=noopener to external links', function () { expect($html)->toContain('rel="noopener noreferrer nofollow"'); }); +test('sanitizeRenderedHtml keeps allowed formatting tags', function () { + $html = ContentSanitizer::sanitizeRenderedHtml('

    Bold and italic with link

    '); + + expect($html) + ->toContain('

    ') + ->toContain('Bold') + ->toContain('italic') + ->toContain('toContain('rel="noopener noreferrer nofollow"'); +}); + +test('sanitizeRenderedHtml strips script tags and event handlers', function () { + $html = ContentSanitizer::sanitizeRenderedHtml('

    Hello

    '); + + expect($html) + ->not()->toContain('not()->toContain('onclick') + ->toContain('Hello'); +}); + +test('sanitizeRenderedHtml strips javascript links', function () { + $html = ContentSanitizer::sanitizeRenderedHtml('click'); + + expect($html) + ->not()->toContain('javascript:') + ->toContain('click'); +}); + // ── Legacy HTML conversion ──────────────────────────────────────────────────── test('render converts legacy bold HTML to markdown output', function () {