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
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?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 /-->"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user