fix: StoredNodeGuard checks URLs, value keys and library ids strictly (P17)
URLs must be sanitizer-stable, keys inside values follow ValueCleaner::VALUE_KEY, instances need a digits-only globalModule; state keys reuse AttrWriter::STATES. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,9 @@ final class StoredNodeGuardTest extends TestCase
|
||||
);
|
||||
$sanitizer = ComposeFixture::sanitizer($unfiltered);
|
||||
|
||||
return new StoredNodeGuard(new ValueCleaner(DiviFixtures::catalog(), $references, $sanitizer), $references, $sanitizer);
|
||||
$cleaner = new ValueCleaner(DiviFixtures::catalog(), $references, $sanitizer);
|
||||
|
||||
return new StoredNodeGuard($cleaner, $references, $sanitizer);
|
||||
}
|
||||
|
||||
private static function block(string $markup): Block
|
||||
@@ -88,7 +90,8 @@ final class StoredNodeGuardTest extends TestCase
|
||||
self::assertSame([], self::guard()->problems($index->find('g0')));
|
||||
self::assertSame([], self::guard()->problems($link));
|
||||
self::assertSame([], self::guard()->problems($title));
|
||||
self::assertSame([], self::guard()->problems(self::block(self::text('<p>Tom & <strong>Jerry</strong></p>'))));
|
||||
$rich = self::block(self::text('<p>Tom & <strong>Jerry</strong></p>'));
|
||||
self::assertSame([], self::guard()->problems($rich));
|
||||
}
|
||||
|
||||
/** @return array<string, array{string}> */
|
||||
@@ -117,7 +120,8 @@ final class StoredNodeGuardTest extends TestCase
|
||||
/** @return array<string, array{string, string, 2?: bool}> Markup, part of the problem, parsed opaque. */
|
||||
public static function refused(): array
|
||||
{
|
||||
$section = static fn (string $inner): string => '<!-- wp:divi/section --><!-- wp:divi/row --><!-- wp:divi/column -->'
|
||||
$section = static fn (string $inner): string => '<!-- wp:divi/section --><!-- wp:divi/row -->'
|
||||
. '<!-- wp:divi/column -->'
|
||||
. $inner . '<!-- /wp:divi/column --><!-- /wp:divi/row --><!-- /wp:divi/section -->';
|
||||
|
||||
return [
|
||||
@@ -189,7 +193,10 @@ final class StoredNodeGuardTest extends TestCase
|
||||
true,
|
||||
],
|
||||
'instance with local attributes that are no object' => [
|
||||
self::node('divi/global-layout', ['globalModule' => '5', 'blockName' => 'divi/text', 'localAttrs' => 'x']),
|
||||
self::node(
|
||||
'divi/global-layout',
|
||||
['globalModule' => '5', 'blockName' => 'divi/text', 'localAttrs' => 'x']
|
||||
),
|
||||
'nicht lesbar',
|
||||
true,
|
||||
],
|
||||
@@ -237,6 +244,23 @@ final class StoredNodeGuardTest extends TestCase
|
||||
])]]),
|
||||
'button.innerContent',
|
||||
],
|
||||
'url the sanitizer would change' => [
|
||||
self::node('divi/button', ['button' => ['innerContent' => self::desktop([
|
||||
'linkUrl' => 'https://kunde.test/"data-probe="1',
|
||||
])]]),
|
||||
'button.innerContent.linkUrl',
|
||||
],
|
||||
'odd key inside a value' => [
|
||||
self::node('divi/text', ['module' => ['decoration' => ['spacing' => self::desktop([
|
||||
'<b data-probe="1">' => '1px',
|
||||
])]]]),
|
||||
'Schlüssel',
|
||||
],
|
||||
'instance with a non-numeric library id' => [
|
||||
self::node('divi/global-layout', ['globalModule' => '5x', 'blockName' => 'divi/text']),
|
||||
'nicht lesbar',
|
||||
true,
|
||||
],
|
||||
'control character' => [self::text('<p>a' . chr(1) . 'b</p>'), 'Steuerzeichen'],
|
||||
// Stored $variable references: the same check as client references (VariableRef).
|
||||
'script in before' => [
|
||||
|
||||
Reference in New Issue
Block a user