fix: Task 5 review round 1 - restore point inside the kses window, strict map field types (S37)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,12 @@ final class ComposeFixture
|
||||
{
|
||||
return $this->unfiltered;
|
||||
}
|
||||
|
||||
/** Every post is readable but 666 (ruling S37, select_post settings). */
|
||||
public function canReadPost(int $id): bool
|
||||
{
|
||||
return $id !== 666;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -431,4 +431,51 @@ final class VariableRefTest extends TestCase
|
||||
self::assertTrue(VariableRef::contains('a $variable( b'));
|
||||
self::assertFalse(VariableRef::contains('Preis: 5 $'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruling S37 (M-1/M-3): map field types come from a filter – untrusted. url → url() (a URL the
|
||||
* sanitizer empties is refused), select_post → a readable numeric post id, select /
|
||||
* yes_no_button / number → plain values; every other type is refused.
|
||||
*/
|
||||
public function testMapFieldTypesAreRoutedStrictly(): void
|
||||
{
|
||||
$ref = self::ref([
|
||||
'evil' => ['link' => 'url', 'color' => 'color', 'blank' => '', 'flag' => 'yes_no_button', 'n' => 'number'],
|
||||
'post_link_url_page' => ['post_id' => 'select_post'],
|
||||
]);
|
||||
$sanitizer = ComposeFixture::sanitizer();
|
||||
|
||||
self::assertSame(
|
||||
self::content('evil', '{"link":"https://kunde.test/a%20b","flag":"on","n":3}'),
|
||||
$ref->canonical(self::content('evil', '{"link":" https://kunde.test/a b","flag":"on","n":3}'), $sanitizer)
|
||||
);
|
||||
self::assertSame(
|
||||
self::content('post_link_url_page', '{"post_id":"12"}'),
|
||||
$ref->canonical(self::content('post_link_url_page', '{"post_id":"12"}'), $sanitizer)
|
||||
);
|
||||
self::assertSame(
|
||||
self::content('post_link_url_page', '{"post_id":12}'),
|
||||
$ref->canonical(self::content('post_link_url_page', '{"post_id":12}'), $sanitizer)
|
||||
);
|
||||
|
||||
$rejected = [
|
||||
'javascript: in a url setting' => [self::content('evil', '{"link":"javascript:alert(1)"}'), 'URL'],
|
||||
'url setting not a string' => [self::content('evil', '{"link":5}'), 'nur Text'],
|
||||
'unknown field type' => [self::content('evil', '{"color":"red"}'), 'Feldtyp'],
|
||||
'empty field type' => [self::content('evil', '{"blank":"x"}'), 'Feldtyp'],
|
||||
'post slug' => [self::content('post_link_url_page', '{"post_id":"impressum"}'), 'Beitrags-ID'],
|
||||
'zero post id' => [self::content('post_link_url_page', '{"post_id":0}'), 'Beitrags-ID'],
|
||||
'negative post id' => [self::content('post_link_url_page', '{"post_id":"-3"}'), 'Beitrags-ID'],
|
||||
'unreadable post' => [self::content('post_link_url_page', '{"post_id":"666"}'), 'Beitrags-ID'],
|
||||
];
|
||||
foreach ($rejected as $case => [$value, $fragment]) {
|
||||
try {
|
||||
$ref->canonical($value, $sanitizer);
|
||||
self::fail('Accepted: ' . $case);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
self::assertStringContainsString($fragment, $e->getMessage(), $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user