From 6c6ce0ce12619bb54823d0f4d55b436e008a6152 Mon Sep 17 00:00:00 2001 From: Tony Date: Sun, 21 Jan 2024 16:32:37 +0000 Subject: [PATCH] fix: codeql incomplete multi-character sanitization (#14298) --- lib/routes/us/supremecourt/argument-audio.js | 15 +++++++++------ lib/v2/kcna/news.js | 5 ++--- lib/v2/xueqiu/hots.js | 3 ++- lib/v2/xueqiu/router.js | 2 +- lib/v2/xueqiu/stock-comments.js | 4 ++-- lib/v2/xueqiu/stock-info.js | 3 ++- lib/v2/xueqiu/user.js | 3 ++- website/docs/routes/finance.mdx | 2 +- 8 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/routes/us/supremecourt/argument-audio.js b/lib/routes/us/supremecourt/argument-audio.js index 5326b8b5a..37120ec43 100644 --- a/lib/routes/us/supremecourt/argument-audio.js +++ b/lib/routes/us/supremecourt/argument-audio.js @@ -1,5 +1,7 @@ const got = require('@/utils/got'); const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); module.exports = async (ctx) => { const year = ctx.params.year || new Date().getFullYear(); @@ -14,15 +16,15 @@ module.exports = async (ctx) => { const $ = cheerio.load(response.data); - const list = $('.panel-body table tbody tr td span a') - .map((_, item) => { + const list = $('.card-body table tbody tr td span a') + .toArray() + .map((item) => { item = $(item); return { title: item.text(), - link: `${rootUrl}/oral_arguments${item.attr('href').replace('..', '')}`, + link: new URL(item.attr('href'), currentUrl).href, }; - }) - .get(); + }); const items = await Promise.all( list.map((item) => @@ -37,7 +39,7 @@ module.exports = async (ctx) => { item.description = content('#pagemaindiv').html(); item.title += ` : ${content('#ctl00_ctl00_MainEditable_mainContent_lblCaseName').text()}`; - item.pubDate = new Date(content('#ctl00_ctl00_MainEditable_mainContent_lblDate').text() + ' GMT-5').toUTCString(); + item.pubDate = timezone(parseDate(content('#ctl00_ctl00_MainEditable_mainContent_lblDate').text()), -5); item.itunes_item_image = imageUrl; item.enclosure_url = content('audio source').attr('src'); @@ -54,5 +56,6 @@ module.exports = async (ctx) => { item: items, itunes_author: 'Supreme Court of the United States', image: imageUrl, + allowEmpty: true, }; }; diff --git a/lib/v2/kcna/news.js b/lib/v2/kcna/news.js index 0c49e0732..ab3e0a026 100644 --- a/lib/v2/kcna/news.js +++ b/lib/v2/kcna/news.js @@ -4,6 +4,7 @@ const asyncPool = require('tiny-async-pool'); const { art } = require('@/utils/render'); const { parseJucheDate, fixDesc, fetchPhoto, fetchVideo } = require('./utils'); const path = require('path'); +const sanitizeHtml = require('sanitize-html'); module.exports = async (ctx) => { const { lang, category = '1ee9bdb7186944f765208f34ecfb5407' } = ctx.params; @@ -15,9 +16,7 @@ module.exports = async (ctx) => { const $ = cheerio.load(response.data); // fix ??? - const title = $('head > title') - .text() - .replaceAll(/<[^>]*>/g, ''); + const title = sanitizeHtml($('head > title').text(), { allowedTags: [], allowedAttributes: {} }); const list = $('.article-link li a') .map((_, item) => { diff --git a/lib/v2/xueqiu/hots.js b/lib/v2/xueqiu/hots.js index ffd1376e9..13e5f3146 100644 --- a/lib/v2/xueqiu/hots.js +++ b/lib/v2/xueqiu/hots.js @@ -1,6 +1,7 @@ const got = require('@/utils/got'); const queryString = require('query-string'); const { parseDate } = require('@/utils/parse-date'); +const sanitizeHtml = require('sanitize-html'); module.exports = async (ctx) => { const res1 = await got({ @@ -34,7 +35,7 @@ module.exports = async (ctx) => { item: data.map((item) => { const description = item.text; return { - title: item.title ?? description.replaceAll(/<[^>]+>/g, ''), + title: item.title ?? sanitizeHtml(description, { allowedTags: [], allowedAttributes: {} }), description: item.text, pubDate: parseDate(item.created_at), link: `https://xueqiu.com${item.target}`, diff --git a/lib/v2/xueqiu/router.js b/lib/v2/xueqiu/router.js index 678520d3d..75a18b264 100644 --- a/lib/v2/xueqiu/router.js +++ b/lib/v2/xueqiu/router.js @@ -4,7 +4,7 @@ module.exports = (router) => { router.get('/fund/:id', require('./fund')); router.get('/hots', require('./hots')); router.get('/snb/:id', require('./snb')); - router.get('/stock_comments/:id/:titleLength?', require('./stock-comments')); + router.get('/stock_comments/:id', require('./stock-comments')); router.get('/stock_info/:id/:type?', require('./stock-info')); router.get('/today', require('./today')); router.get('/user/:id/:type?', require('./user')); diff --git a/lib/v2/xueqiu/stock-comments.js b/lib/v2/xueqiu/stock-comments.js index e7d584c7f..769d65383 100644 --- a/lib/v2/xueqiu/stock-comments.js +++ b/lib/v2/xueqiu/stock-comments.js @@ -3,10 +3,10 @@ const cheerio = require('cheerio'); const { art } = require('@/utils/render'); const path = require('path'); const { parseDate } = require('@/utils/parse-date'); +const sanitizeHtml = require('sanitize-html'); module.exports = async (ctx) => { const id = ctx.params.id; - const titleLength = ctx.params.titleLength ? Number.parseInt(ctx.params.titleLength) : 30; const res = await got({ method: 'get', @@ -35,7 +35,7 @@ module.exports = async (ctx) => { } const description = art(path.join(__dirname, 'templates/comments_description.art'), { item }); return { - title: item.title === '' ? item.text.replaceAll(/<[^>]+>/g, '').slice(0, titleLength) : item.title, + title: item.title || sanitizeHtml(item.text, { allowedTags: [], allowedAttributes: {} }), description, pubDate: parseDate(item.created_at), link, diff --git a/lib/v2/xueqiu/stock-info.js b/lib/v2/xueqiu/stock-info.js index ad58a7703..3bd3589c7 100644 --- a/lib/v2/xueqiu/stock-info.js +++ b/lib/v2/xueqiu/stock-info.js @@ -2,6 +2,7 @@ const got = require('@/utils/got'); const cheerio = require('cheerio'); const queryString = require('query-string'); const { parseDate } = require('@/utils/parse-date'); +const sanitizeHtml = require('sanitize-html'); module.exports = async (ctx) => { const id = ctx.params.id; @@ -58,7 +59,7 @@ module.exports = async (ctx) => { link = item.quote_cards[0].target_url; } return { - title: item.title === '' ? item.description.replaceAll(/<[^>]+>/g, '') : item.title, + title: item.title || sanitizeHtml(item.description, { allowedTags: [], allowedAttributes: {} }), description: item.description, pubDate: parseDate(item.created_at), link, diff --git a/lib/v2/xueqiu/user.js b/lib/v2/xueqiu/user.js index c33a94cd6..f2e6c7d87 100644 --- a/lib/v2/xueqiu/user.js +++ b/lib/v2/xueqiu/user.js @@ -1,6 +1,7 @@ const got = require('@/utils/got'); const queryString = require('query-string'); const { parseDate } = require('@/utils/parse-date'); +const sanitizeHtml = require('sanitize-html'); const rootUrl = 'https://xueqiu.com'; @@ -57,7 +58,7 @@ module.exports = async (ctx) => { const description = item.description + retweetedStatus; return { - title: item.title ?? description.replaceAll(/<[^>]+>/g, ''), + title: item.title ?? sanitizeHtml(description, { allowedTags: [], allowedAttributes: {} }), description: item.text ? item.text + retweetedStatus : description, pubDate: parseDate(item.created_at), link: rootUrl + item.target, diff --git a/website/docs/routes/finance.mdx b/website/docs/routes/finance.mdx index e556cebbe..2e56442b6 100644 --- a/website/docs/routes/finance.mdx +++ b/website/docs/routes/finance.mdx @@ -742,7 +742,7 @@ TokenInsight also provides official RSS, you can take a look at [https://api.tok ### 股票评论 {#xue-qiu-gu-piao-ping-lun} - + ### 热帖 {#xue-qiu-re-tie}