@@ -616,6 +616,10 @@ public function attributesAreEncoded(string $payload, string $expectation): void
616616
617617 public static function specialTagsAreHandledDataProvider (): iterable
618618 {
619+ yield 'noscript valid ' => [
620+ '<noscript><p id="info">This site requires JavaScript.</p></noscript> ' ,
621+ '<noscript><p id="info">This site requires JavaScript.</p></noscript> ' ,
622+ ];
619623 yield 'noscript attribute ' => [
620624 '<noscript><p id="</noscript><script>alert(1)</script>"></p> ' ,
621625 '<noscript><p id="</noscript><script>alert(1)</script>"></p></noscript> ' ,
@@ -662,4 +666,64 @@ public function specialTagsAreHandled(string $payload, string $expectation): voi
662666 );
663667 self ::assertSame ($ expectation , $ sanitizer ->sanitize ($ payload ));
664668 }
669+
670+ public static function insecureRawTextIsSanitizedDataProvider (): \Generator
671+ {
672+ $ noscript = new Behavior \Tag ('noscript ' , Behavior \Tag::ALLOW_CHILDREN );
673+ $ styleDefault = new Behavior \Tag ('style ' , Behavior \Tag::ALLOW_CHILDREN );
674+ $ styleInsecureRawText = new Behavior \Tag ('style ' , Behavior \Tag::ALLOW_CHILDREN | Behavior \Tag::ALLOW_INSECURE_RAW_TEXT );
675+ $ iframeDefault = new Behavior \Tag ('iframe ' , Behavior \Tag::ALLOW_CHILDREN );
676+ $ iframeInsecureRawText = new Behavior \Tag ('iframe ' , Behavior \Tag::ALLOW_CHILDREN | Behavior \Tag::ALLOW_INSECURE_RAW_TEXT );
677+
678+ yield 'style whitespace closing tag is recognized (img is removed - default) ' => [
679+ [$ styleDefault ],
680+ "<style>div::after{content:'<'}</style \t><img src=x onerror=alert(1)> " ,
681+ '<style>div::after{content: \'< \'}</style> ' ,
682+ ];
683+ yield 'style whitespace closing tag is recognised (img is removed - insecure raw text allowed) ' => [
684+ [$ styleInsecureRawText ],
685+ "<style>div::after{content:'<'}</style \t><img src=x onerror=alert(1)> " ,
686+ '<style>div::after{content: \'< \'}</style> ' ,
687+ ];
688+
689+ yield 'iframe & style detect raw-text part (img is removed - insecure raw text allowed) ' => [
690+ [$ iframeInsecureRawText , $ styleInsecureRawText ],
691+ '<iframe><style></iframe><img src="x" onerror="alert(1)"></style></iframe> ' ,
692+ '<iframe><style></iframe> ' ,
693+ ];
694+ yield 'iframe & style detect raw-text part (img is removed - default) ' => [
695+ [$ iframeDefault , $ styleDefault ],
696+ '<iframe><style></iframe><img src="x" onerror="alert(1)"></style></iframe> ' ,
697+ '<iframe><style></iframe> ' ,
698+ ];
699+
700+ yield 'noscript nesting another raw-text element is denied (content is encoded - default) ' => [
701+ [$ noscript , $ styleDefault ],
702+ '<noscript><style></noscript><img src=x onerror=alert(2)></style></noscript> ' ,
703+ '<noscript><style></noscript><img src=x onerror=alert(2)></style></noscript> ' ,
704+ ];
705+ yield 'noscript nesting another raw-text element is denied (content is encoded - insecure raw text allowed) ' => [
706+ [$ noscript , $ styleInsecureRawText ],
707+ '<noscript><style></noscript><img src=x onerror=alert(2)></style></noscript> ' ,
708+ '<noscript><style></noscript><img src=x onerror=alert(2)></style></noscript> ' ,
709+ ];
710+ }
711+
712+ /**
713+ * @test
714+ * @dataProvider insecureRawTextIsSanitizedDataProvider
715+ */
716+ public function insecureRawTextIsSanitized (array $ tags , string $ payload , string $ expectation ): void
717+ {
718+ $ behavior = (new Behavior ())
719+ ->withFlags (Behavior::REMOVE_UNEXPECTED_CHILDREN )
720+ ->withName ('scenario-test ' )
721+ ->withTags (...$ tags );
722+
723+ $ sanitizer = new Sanitizer (
724+ $ behavior ,
725+ new CommonVisitor ($ behavior )
726+ );
727+ self ::assertSame ($ expectation , $ sanitizer ->sanitize ($ payload ));
728+ }
665729}
0 commit comments