File tree Expand file tree Collapse file tree 3 files changed +38
-4
lines changed
Expand file tree Collapse file tree 3 files changed +38
-4
lines changed Original file line number Diff line number Diff line change @@ -31,9 +31,7 @@ export function tagToString<T extends HeadTag>(tag: T) {
3131 return SelfClosingTags . has ( tag . tag ) ? openTag : `${ openTag } </${ tag . tag } >`
3232
3333 // dangerously using innerHTML, we don't encode this
34- let content = String ( tag . innerHTML || '' )
35- if ( tag . textContent )
36- // content needs to be encoded to avoid XSS, only for title
37- content = escapeHtml ( String ( tag . textContent ) )
34+ let content = String ( tag . textContent || tag . innerHTML || '' )
35+ content = tag . tag === 'title' ? escapeHtml ( content ) : content . replace ( new RegExp ( `<\/${ tag . tag } ` , 'gi' ) , `<\\/${ tag . tag } ` )
3836 return SelfClosingTags . has ( tag . tag ) ? openTag : `${ openTag } ${ content } </${ tag . tag } >`
3937}
Original file line number Diff line number Diff line change 1+ import { createHead } from '@unhead/dom'
12import { describe , it } from 'vitest'
23import { useHead , useSeoMeta } from '../../../src'
34import { renderSSRHead } from '../../../src/server'
@@ -356,4 +357,24 @@ describe('ssr', () => {
356357 expect ( processedHtml ) . toContain ( '<link rel="prefetch" href="another-script.js">' )
357358 expect ( processedHtml ) . toContain ( '<script src="another-script.js"></script>' )
358359 } )
360+ it ( '#541' , async ( ) => {
361+ const input = `
362+ <head>
363+ <style>
364+ html { background: url(/foo.png); }
365+ img::before { content: "foo"; }
366+ </style>
367+ </head>
368+ `
369+ const processedHtml = await transformHtmlTemplate ( createHead ( ) , input )
370+ expect ( processedHtml ) . toMatchInlineSnapshot ( `
371+ "
372+ <head>
373+ <style>
374+ html { background: url(/foo.png); }
375+ img::before { content: "foo"; }
376+ </style></head>
377+ "
378+ ` )
379+ } )
359380} )
Original file line number Diff line number Diff line change @@ -351,4 +351,19 @@ describe('xss', () => {
351351 <link rel="stylesheet" href="vbscript:alert(1)">"
352352 ` )
353353 } )
354+ it ( 'style tag' , async ( ) => {
355+ // body {color: red;}</style><script>alert('XSS')</script><style>
356+ const head = createServerHeadWithContext ( )
357+ head . push ( {
358+ style : [
359+ { innerHTML : 'body {color: red;}</style><script>alert(\'XSS\')</script><style>' } ,
360+ { innerHTML : '} </style><script>alert("XSS Attack Successful")</script><style>{</style>' } ,
361+ ] ,
362+ } )
363+ const ctx = await renderSSRHead ( head )
364+ expect ( ctx . headTags ) . toMatchInlineSnapshot ( `
365+ "<style>body {color: red;}<\\/style><script>alert('XSS')</script><style></style>
366+ <style>} <\\/style><script>alert("XSS Attack Successful")</script><style>{<\\/style></style>"
367+ ` )
368+ } )
354369} )
You can’t perform that action at this time.
0 commit comments