fix: closes #10682, strip unicode control chars

that explode rss module
This commit is contained in:
Barış Soner Uşaklı
2026-01-20 20:50:04 -05:00
parent d3f653e648
commit d867d8adbb

View File

@@ -61,6 +61,11 @@ async function validateTokenIfRequiresLogin(requiresLogin, cid, req, res) {
return true; return true;
} }
function stripUnicodeControlChars(str) {
// eslint-disable-next-line no-control-regex
return str.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, '');
}
async function generateForTopic(req, res, next) { async function generateForTopic(req, res, next) {
if (meta.config['feeds:disableRSS']) { if (meta.config['feeds:disableRSS']) {
return next(); return next();
@@ -80,20 +85,21 @@ async function generateForTopic(req, res, next) {
if (await validateTokenIfRequiresLogin(!userPrivileges['topics:read'], topic.cid, req, res)) { if (await validateTokenIfRequiresLogin(!userPrivileges['topics:read'], topic.cid, req, res)) {
const topicData = await topics.getTopicWithPosts(topic, `tid:${tid}:posts`, req.uid || req.query.uid || 0, 0, 24, true); const topicData = await topics.getTopicWithPosts(topic, `tid:${tid}:posts`, req.uid || req.query.uid || 0, 0, 24, true);
const mainPost = topicData.posts[0];
topics.modifyPostsByPrivilege(topicData, userPrivileges); topics.modifyPostsByPrivilege(topicData, userPrivileges);
const title = stripUnicodeControlChars(topicData.title);
const feed = new rss({ const feed = new rss({
title: utils.stripHTMLTags(topicData.title, utils.tags), title: utils.stripHTMLTags(title, utils.tags),
description: topicData.posts.length ? topicData.posts[0].content : '', description: topicData.posts.length ? stripUnicodeControlChars(mainPost.content) : '',
feed_url: `${nconf.get('url')}/topic/${tid}.rss`, feed_url: `${nconf.get('url')}/topic/${tid}.rss`,
site_url: `${nconf.get('url')}/topic/${topicData.slug}`, site_url: `${nconf.get('url')}/topic/${topicData.slug}`,
image_url: topicData.posts.length ? topicData.posts[0].picture : '', image_url: topicData.posts.length ? mainPost.picture : '',
author: topicData.posts.length ? topicData.posts[0].username : '', author: topicData.posts.length ? mainPost.username : '',
ttl: 60, ttl: 60,
}); });
if (topicData.posts.length > 0) { if (topicData.posts.length > 0) {
feed.pubDate = new Date(parseInt(topicData.posts[0].timestamp, 10)).toUTCString(); feed.pubDate = new Date(parseInt(mainPost.timestamp, 10)).toUTCString();
} }
const replies = topicData.posts.slice(1); const replies = topicData.posts.slice(1);
replies.forEach((postData) => { replies.forEach((postData) => {
@@ -103,8 +109,8 @@ async function generateForTopic(req, res, next) {
).toUTCString(); ).toUTCString();
feed.item({ feed.item({
title: `Reply to ${utils.stripHTMLTags(topicData.title, utils.tags)} on ${dateStamp}`, title: `Reply to ${utils.stripHTMLTags(title, utils.tags)} on ${dateStamp}`,
description: postData.content, description: stripUnicodeControlChars(postData.content),
url: `${nconf.get('url')}/post/${postData.pid}`, url: `${nconf.get('url')}/post/${postData.pid}`,
author: postData.user ? postData.user.username : '', author: postData.user ? postData.user.username : '',
date: dateStamp, date: dateStamp,