@astrojs/rss: XML Injection via Unescaped RSS Feed Fields
Summary
In @astrojs/rss, the source.title and enclosure.type item fields are interpolated directly into XML template strings without XML-character escaping before being parsed by fast-xml-parser. An attacker who controls these field values can inject arbitrary XML elements into the generated RSS feed.
Details
Two fields in packages/astro-rss/src/index.ts are affected:
source.title
item.source = parser.parse(
${result.source.title},
).source;source.title is validated only as z.string(), with no restriction on XML special characters. A value containing ` followed by arbitrary XML is parsed as real XML elements, merging injected nodes into the RSS item.
enclosure.type
item.enclosure = parser.parse(, ).enclosure;
enclosure.type is also z.string() and is interpolated into an XML attribute without escaping. A value containing " followed by additional XML can break out of the attribute and inject extra elements.
Proof of Concept
source.title injection:
source: {
url: 'https://legit.example.com',
title: 'INJECTEDhttps://evil.com',
}
// Result: RSS feed contains an injected element with an evil.com linkenclosure.type injection:
enclosure: {
url: 'https://example.com/a.mp3',
length: 0,
type: 'audio/mpeg" />https://evil.example.com elementBoth injections were confirmed with fast-xml-parser: the injected "link": "https://evil.com" appears in the parsed output.
Impact
An attacker who can control source.title or enclosure.type values (e.g., via a CMS, database, or user-submitted content that populates RSSFeedItem) can inject arbitrary XML into the generated RSS feed. This corrupts feed structure, injects false metadata (e.g., a fake pointing to a malicious URL), and can cause feed readers to misparse or display attacker-controlled content. In SSR mode (output: 'server'), the poisoned feed is served on every request to all subscribers.
Patches
Fixed in @astrojs/[email protected]`.