| import 'package:html/parser.dart'; |
| import 'package:test/test.dart'; |
| |
| void main() { |
| group('Mutation XSS Prevention (Namespace-aware raw-text serialization)', () { |
| void verifySafeSerialization(String outerTag, String innerTag) { |
| test('Escapes < inside <$outerTag><$innerTag>', () { |
| final payload = '<img src=x onerror=alert(1)>'; |
| final input = '<$outerTag><$innerTag>$payload</$innerTag></$outerTag>'; |
| final doc = parse(input); |
| |
| final output = doc.body!.innerHtml; |
| |
| // Output must retain < and > escaped |
| expect( |
| output, '<$outerTag><$innerTag>$payload</$innerTag></$outerTag>'); |
| |
| // Ensure that a reparse doesn't mutate it into a live <img> tag |
| final reparsedDoc = parse(output); |
| expect(reparsedDoc.querySelector('img'), isNull, |
| reason: 'img should remain escaped text'); |
| }); |
| } |
| |
| verifySafeSerialization('svg', 'style'); |
| verifySafeSerialization('svg', 'iframe'); |
| verifySafeSerialization('svg', 'xmp'); |
| |
| verifySafeSerialization('math', 'style'); |
| verifySafeSerialization('math', 'iframe'); |
| verifySafeSerialization('math', 'xmp'); |
| }); |
| } |