Value => part of the German error.
*/
public static function malicious(): array
{
$content = static fn (string $name, string $settings): string =>
'$variable({"type":"content","value":{"name":"' . $name . '","settings":' . $settings . '}})$';
return [
'script in before' => [$content('post_title', '{"before":"","after":""}'), 'before'],
'script in after' => [$content('post_title', '{"before":"","after":"
"}'), 'after'],
'escaped script in before' => [
$content('post_title', '{"before":"","after":""}'),
'before',
],
'tags in date format' => [$content('post_date', '{"date_format":"d"}'), 'date_format'],
'type evil' => ['$variable({"type":"evil","value":{"name":"gcid-a1b2","settings":{}}})$', 'Typ'],
'unknown gcid' => ['$variable({"type":"color","value":{"name":"gcid-nope","settings":{}}})$', 'gcid-nope'],
'unknown gvid' => [$content('gvid-nope', '{}'), 'gvid-nope'],
'content gvid as color' => ['$variable({"type":"color","value":{"name":"gvid-s1","settings":{}}})$', 'gvid-s1'],
'color gcid as content' => [$content('gcid-a1b2', '{}'), 'gcid-a1b2'],
'name with paren' => ['$variable({"type":"color","value":{"name":"gcid-a1b2)","settings":{}}})$', 'Name'],
'name with style breakout' => [
'$variable({"type":"color","value":{"name":"gcid-a1b2;}","settings":{}}})$',
'Name',
],
'unknown settings key' => [$content('post_title', '{"before":"","foo":"1"}'), 'foo'],
'enable_html' => [$content('custom_meta_telefon', '{"before":"","after":"","enable_html":"on"}'), 'enable_html'],
'color setting not numeric' => [
'$variable({"type":"color","value":{"name":"gcid-a1b2","settings":{"opacity":"1;}"}}})$',
'opacity',
],
'protected meta key' => [$content('custom_meta__edit_lock', '{}'), 'custom_meta__edit_lock'],
'unknown dynamic content' => [$content('post_meta_key', '{}'), 'post_meta_key'],
'extra top-level key' => ['$variable({"type":"color","value":{"name":"gcid-a1b2","settings":{}},"x":1})$', 'x'],
'extra value key' => ['$variable({"type":"color","value":{"name":"gcid-a1b2","settings":{},"x":1}})$', 'x'],
'greedy smuggling' => ['$variable({"a":"})$"})$', 'allein im Wert'],
'nested reference in before' => [
$content('post_title', '{"before":"$variable(x)$","after":""}'),
'allein im Wert',
],
'broken json' => ['$variable(kaputt)$', 'JSON'],
'trailing text' => [$content('post_title', '{}') . ' ', 'allein im Wert'],
'embedded in text' => ['Hi ' . $content('post_title', '{"before":"","after":""}') . '
', 'allein im Wert'],
];
}
/** @dataProvider malicious */
public function testRejectsMaliciousReferences(string $input, string $message): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage($message);
self::ref()->canonical($input, ComposeFixture::sanitizer());
}
public function testUrlFieldsTakeContentReferencesWithoutBeforeOrAfter(): void
{
$ref = self::ref();
$link = '$variable({"type":"content","value":{"name":"post_link_url","settings":{}}})$';
self::assertSame($link, $ref->canonical($link, ComposeFixture::sanitizer(), true));
foreach (
[
'$variable({"type":"content","value":{"name":"post_link_url","settings":{"before":"javascript:alert(1)//","after":""}}})$',
'$variable({"type":"color","value":{"name":"gcid-a1b2","settings":{}}})$',
] as $value
) {
try {
$ref->canonical($value, ComposeFixture::sanitizer(), true);
self::fail('Accepted in a URL field: ' . $value);
} catch (InvalidArgumentException $e) {
self::assertStringContainsString('URL', $e->getMessage());
}
}
}
public function testDetectsReferences(): void
{
self::assertTrue(VariableRef::contains('a $variable( b'));
self::assertFalse(VariableRef::contains('Preis: 5 $'));
}
}