Skip to content

Commit 33398bc

Browse files
authored
fix: escape all user-provided XML fields (#610)
1 parent 9ef0a8e commit 33398bc

2 files changed

Lines changed: 13 additions & 13 deletions

File tree

src/runtime/server/sitemap/builder/xml.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ function buildUrlXml(url: ResolvedSitemapUrl, NL: string, I1: string, I2: string
2020
if (url.loc)
2121
xml += `${I2}<loc>${xmlEscape(url.loc)}</loc>${NL}`
2222
if (url.lastmod)
23-
xml += `${I2}<lastmod>${url.lastmod}</lastmod>${NL}`
23+
xml += `${I2}<lastmod>${xmlEscape(url.lastmod)}</lastmod>${NL}`
2424
if (url.changefreq)
25-
xml += `${I2}<changefreq>${url.changefreq}</changefreq>${NL}`
25+
xml += `${I2}<changefreq>${xmlEscape(url.changefreq)}</changefreq>${NL}`
2626
if (url.priority !== undefined) {
2727
const p = typeof url.priority === 'number' ? url.priority : Number.parseFloat(url.priority)
2828
xml += `${I2}<priority>${p.toFixed(1)}</priority>${NL}`
@@ -62,27 +62,27 @@ function buildUrlXml(url: ResolvedSitemapUrl, NL: string, I1: string, I2: string
6262
if (video.player_loc)
6363
xml += `${I3}<video:player_loc>${xmlEscape(video.player_loc as string)}</video:player_loc>${NL}`
6464
if (video.duration !== undefined)
65-
xml += `${I3}<video:duration>${video.duration}</video:duration>${NL}`
65+
xml += `${I3}<video:duration>${escapeValueForXml(video.duration)}</video:duration>${NL}`
6666
if (video.expiration_date)
67-
xml += `${I3}<video:expiration_date>${video.expiration_date}</video:expiration_date>${NL}`
67+
xml += `${I3}<video:expiration_date>${xmlEscape(video.expiration_date)}</video:expiration_date>${NL}`
6868
if (video.rating !== undefined)
69-
xml += `${I3}<video:rating>${video.rating}</video:rating>${NL}`
69+
xml += `${I3}<video:rating>${escapeValueForXml(video.rating)}</video:rating>${NL}`
7070
if (video.view_count !== undefined)
71-
xml += `${I3}<video:view_count>${video.view_count}</video:view_count>${NL}`
71+
xml += `${I3}<video:view_count>${escapeValueForXml(video.view_count)}</video:view_count>${NL}`
7272
if (video.publication_date)
73-
xml += `${I3}<video:publication_date>${video.publication_date}</video:publication_date>${NL}`
73+
xml += `${I3}<video:publication_date>${xmlEscape(video.publication_date)}</video:publication_date>${NL}`
7474
if (video.family_friendly !== undefined)
7575
xml += `${I3}<video:family_friendly>${yesNo(video.family_friendly)}</video:family_friendly>${NL}`
7676
if (video.restriction)
77-
xml += `${I3}<video:restriction relationship="${video.restriction.relationship || 'allow'}">${xmlEscape(video.restriction.restriction)}</video:restriction>${NL}`
77+
xml += `${I3}<video:restriction relationship="${xmlEscape(video.restriction.relationship || 'allow')}">${xmlEscape(video.restriction.restriction)}</video:restriction>${NL}`
7878
if (video.platform)
79-
xml += `${I3}<video:platform relationship="${video.platform.relationship || 'allow'}">${xmlEscape(video.platform.platform)}</video:platform>${NL}`
79+
xml += `${I3}<video:platform relationship="${xmlEscape(video.platform.relationship || 'allow')}">${xmlEscape(video.platform.platform)}</video:platform>${NL}`
8080
if (video.requires_subscription !== undefined)
8181
xml += `${I3}<video:requires_subscription>${yesNo(video.requires_subscription)}</video:requires_subscription>${NL}`
8282
if (video.price) {
8383
for (const price of video.price) {
84-
const c = price.currency ? ` currency="${price.currency}"` : ''
85-
const t = price.type ? ` type="${price.type}"` : ''
84+
const c = price.currency ? ` currency="${xmlEscape(price.currency)}"` : ''
85+
const t = price.type ? ` type="${xmlEscape(price.type)}"` : ''
8686
xml += `${I3}<video:price${c}${t}>${xmlEscape(String(price.price ?? ''))}</video:price>${NL}`
8787
}
8888
}
@@ -112,7 +112,7 @@ function buildUrlXml(url: ResolvedSitemapUrl, NL: string, I1: string, I2: string
112112
if (url.news.title)
113113
xml += `${I3}<news:title>${xmlEscape(url.news.title)}</news:title>${NL}`
114114
if (url.news.publication_date)
115-
xml += `${I3}<news:publication_date>${url.news.publication_date}</news:publication_date>${NL}`
115+
xml += `${I3}<news:publication_date>${xmlEscape(url.news.publication_date)}</news:publication_date>${NL}`
116116
xml += `${I2}</news:news>${NL}`
117117
}
118118

src/runtime/server/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { normalizeRuntimeFilters } from '../utils-pure'
88
export * from '../utils-pure'
99

1010
// XML escape function for content inserted into XML/XSL
11-
export function xmlEscape(str: string): string {
11+
export function xmlEscape(str: string | number | boolean | Date): string {
1212
return String(str)
1313
.replace(/&/g, '&amp;')
1414
.replace(/</g, '&lt;')

0 commit comments

Comments
 (0)