Files
janniclas.loosenandClaude Opus 5.5 99eda25452 fix(security): Divi-markup refusal sees content as storage will (ruling S52)
Control characters removed by kses (wp_kses_no_null: C0, \\0 sequences)
or ControlChars (DEL) could hide a divi/* delimiter or an et_pb shortcode
from the raw-input check. The shared DiviMarkup helper checks the raw
and the normalized form and now guards every raw-content path:
content-create/-update content and media-update description (attachment
post_content). MediaImporter logs import failures with scheme, host,
port and path only; uninstall.php lists the removed user meta.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 19:50:31 +02:00

51 lines
2.1 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Abilities;
use LIT\MCP\Abilities\DiviMarkup;
use PHPUnit\Framework\TestCase;
/**
* Ruling S52 (fix round 1 of security audit M1): raw content is checked for Divi markup in the
* form storage will see – after the removals of wp_kses_no_null() (C0 controls, "\0" sequences)
* and ControlChars (plus DEL) –, so control characters inside a delimiter cannot hide it.
*/
final class DiviMarkupTest extends TestCase
{
/** @return array<string, array{string}> */
public static function hidden(): array
{
$cases = [];
foreach (["\0", "\x01", "\x08", "\x0B", "\x0C", "\x1F", "\x7F", '\\0', '\\\\00'] as $i => $c) {
$cases["opener-after-dash $i"] = ["<!--$c wp:divi/text {\"a\":1} /-->"];
$cases["inside-namespace $i"] = ["<!-- wp:di{$c}vi/text /-->"];
$cases["before-slash $i"] = ["<!-- wp:divi$c/text /-->"];
$cases["inside-wp $i"] = ["<!-- w{$c}p:divi/section --><!-- /wp:divi/section -->"];
$cases["closer $i"] = ["<!-- /{$c}wp:divi/row -->"];
$cases["between-dashes $i"] = ["<!-$c- wp:divi/text /-->"];
$cases["shortcode $i"] = ["[et_{$c}pb_section][/et_pb_section]"];
$cases["shortcode-start $i"] = ["[$c/et_pb_text]"];
}
return $cases;
}
/** @dataProvider hidden */
public function testControlCharactersDoNotHideDiviMarkup(string $content): void
{
self::assertTrue(DiviMarkup::contains($content));
}
public function testPlainDelimitersAndOtherMarkup(): void
{
self::assertTrue(DiviMarkup::contains("<!--\t\n wp:divi/text /-->"));
self::assertTrue(DiviMarkup::contains('[et_pb_section]'));
self::assertFalse(DiviMarkup::contains('<!-- wp:paragraph --><p>Divi</p><!-- /wp:paragraph -->'));
self::assertFalse(DiviMarkup::contains('<!--wp:divi/text /-->'), 'no whitespace: no block for the parser');
self::assertFalse(DiviMarkup::contains('<!-- WP:DIVI/text /-->'), 'the parser is case-sensitive');
self::assertSame('<!-- wp:divi/text /-->', DiviMarkup::normalized("<!--\0 wp:di\x7Fvi/text /-->"));
}
}