Skip to content

Commit ea4ff9e

Browse files
committed
[SITE-5450] Fix XSS escaping, strict types, and test gap in tabbed content
Escape tab titles with Html::escape() in the formatter for defense-in-depth, add declare(strict_types=1) to the Search API processor, remove unnecessary @ error suppression from json_decode calls, and add missing tab title assertion in TabbedContentProcessorTest.
1 parent 50d25a5 commit ea4ff9e

File tree

3 files changed

+9
-5
lines changed

3 files changed

+9
-5
lines changed

src/Plugin/Field/FieldFormatter/PantheonTabbedContentFormatter.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Drupal\pantheon_content_publisher\Plugin\Field\FieldFormatter;
66

7+
use Drupal\Component\Utility\Html;
78
use Drupal\Core\Field\FieldDefinitionInterface;
89
use Drupal\Core\Field\FieldItemListInterface;
910
use Drupal\Core\Field\FormatterBase;
@@ -41,7 +42,7 @@ public function viewElements(FieldItemListInterface $items, $langcode): array {
4142
if (empty($item->value)) {
4243
continue;
4344
}
44-
$tabs = @json_decode($item->value, TRUE);
45+
$tabs = json_decode($item->value, TRUE);
4546
if (!is_array($tabs) || empty($tabs)) {
4647
continue;
4748
}
@@ -79,7 +80,7 @@ protected function buildTabs(array $tabs, int $heading_level = 2): array {
7980
'heading' => [
8081
'#type' => 'html_tag',
8182
'#tag' => $tag,
82-
'#value' => $title,
83+
'#value' => Html::escape($title),
8384
],
8485
'content' => $this->renderTabContent($tab['documentTab'] ?? ''),
8586
];
@@ -117,7 +118,7 @@ protected function renderTabContent(string|array $document_tab): array {
117118
return $build ?: ['#markup' => ''];
118119
}
119120
if (is_string($document_tab) && !empty($document_tab)) {
120-
$decoded = @json_decode($document_tab, TRUE);
121+
$decoded = json_decode($document_tab, TRUE);
121122
if ($decoded && is_array($decoded)) {
122123
$build = $this->tagsToRenderable->convertJsonToRenderable($document_tab);
123124
return $build ?: ['#markup' => ''];

src/Plugin/search_api/processor/TabbedContent.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Drupal\pantheon_content_publisher\Plugin\search_api\processor;
46

57
use Drupal\Core\Render\RendererInterface;
@@ -61,7 +63,7 @@ protected function processFieldValue(&$value, $type) {
6163
}
6264

6365
// Parse the TabTree array structure.
64-
if (!$tabbed_content = @json_decode($value, TRUE)) {
66+
if (!$tabbed_content = json_decode($value, TRUE)) {
6567
return;
6668
}
6769

@@ -100,7 +102,7 @@ protected function extractTabContent(array $tabs): array {
100102

101103
if (is_string($document_tab)) {
102104
// Check if it's JSON (PantheonTree) or plain text.
103-
$decoded = @json_decode($document_tab, TRUE);
105+
$decoded = json_decode($document_tab, TRUE);
104106
if ($decoded && is_array($decoded)) {
105107
// It's PantheonTree JSON - process it.
106108
if ($build = $this->tagsToRenderable->convertJsonToRenderable($document_tab)) {

tests/src/Unit/TabbedContentProcessorTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ public function testProcessFieldValueWithArrayDocumentTab(): void {
198198
$this->callProcessFieldValue($value);
199199

200200
$this->assertStringContainsString('Array content', $value);
201+
$this->assertStringContainsString('Array Tab', $value);
201202
}
202203

203204
/**

0 commit comments

Comments
 (0)