@@ -13,6 +13,58 @@ const md = new markdown({
1313 linkify : true ,
1414} ) ;
1515
16+ const SAFE_RICH_TAGS = [
17+ "a" ,
18+ "br" ,
19+ "span" ,
20+ "strong" ,
21+ "em" ,
22+ "code" ,
23+ "blockquote" ,
24+ "p" ,
25+ "pre" ,
26+ "hr" ,
27+ "ul" ,
28+ "ol" ,
29+ "li" ,
30+ "img" ,
31+ "h1" ,
32+ "h2" ,
33+ "h3" ,
34+ "h4" ,
35+ "h5" ,
36+ "h6" ,
37+ "table" ,
38+ "thead" ,
39+ "tbody" ,
40+ "tr" ,
41+ "th" ,
42+ "td" ,
43+ "sup" ,
44+ "sub" ,
45+ "del" ,
46+ "ins" ,
47+ ] ;
48+
49+ const MAX_IMAGE_DIMENSION = 1600 ;
50+
51+ const SAFE_RICH_ATTRS = [
52+ "href" ,
53+ "internal" ,
54+ "target" ,
55+ "rel" ,
56+ "src" ,
57+ "alt" ,
58+ "title" ,
59+ "width" ,
60+ "height" ,
61+ "class" ,
62+ "data-user" ,
63+ "loading" ,
64+ "decoding" ,
65+ "referrerpolicy" ,
66+ ] ;
67+
1668// advancedParser.ts 修改以下部分
1769
1870// 替换原有highlightjs引入
@@ -179,13 +231,41 @@ function processImageTags(html: string): string {
179231
180232 imgTags . forEach ( ( tag ) => {
181233 const src = tag . getAttribute ( "src" ) ;
182- if ( src && ! isAllowedDomain ( src ) ) {
234+
235+ if ( ! src || ! isAllowedDomain ( src ) ) {
183236 tag . remove ( ) ;
184- } else {
185- tag . style . width = tag . getAttribute ( "width" ) || tag . style . width ;
186- tag . style . height = tag . getAttribute ( "height" ) || tag . style . height ;
187- tag . style . maxWidth = "100%" ;
237+ return ;
188238 }
239+
240+ const width = tag . getAttribute ( "width" ) ;
241+ const height = tag . getAttribute ( "height" ) ;
242+
243+ const parsedWidth = width ? Number . parseInt ( width , 10 ) : NaN ;
244+ const parsedHeight = height ? Number . parseInt ( height , 10 ) : NaN ;
245+
246+ if ( ! Number . isFinite ( parsedWidth ) || ! Number . isFinite ( parsedHeight ) ) {
247+ tag . remove ( ) ;
248+ return ;
249+ }
250+
251+ if (
252+ parsedWidth <= 0 ||
253+ parsedHeight <= 0 ||
254+ parsedWidth > MAX_IMAGE_DIMENSION ||
255+ parsedHeight > MAX_IMAGE_DIMENSION
256+ ) {
257+ tag . remove ( ) ;
258+ return ;
259+ }
260+
261+ tag . setAttribute ( "width" , `${ parsedWidth } ` ) ;
262+ tag . setAttribute ( "height" , `${ parsedHeight } ` ) ;
263+ tag . removeAttribute ( "style" ) ;
264+ tag . removeAttribute ( "srcset" ) ;
265+ tag . removeAttribute ( "sizes" ) ;
266+ tag . setAttribute ( "loading" , "lazy" ) ;
267+ tag . setAttribute ( "decoding" , "async" ) ;
268+ tag . setAttribute ( "referrerpolicy" , "no-referrer" ) ;
189269 } ) ;
190270
191271 return doc . body . innerHTML ;
@@ -265,8 +345,19 @@ function parse(text: string | string[], isInline: boolean = false) {
265345 result = processImageTags ( result ) ;
266346
267347 let clean = DOMPurify . sanitize ( result , {
268- ADD_TAGS : [ "a" , "br" , "span" , "img" ] , // 允许<a>>标签和<img>标签
269- ADD_ATTR : [ "href" , "internal" , "src" , "width" , "height" , "maxWidht" ] , // 允许href和data-to属性以及img的src、width和height属性
348+ ALLOWED_TAGS : SAFE_RICH_TAGS ,
349+ ALLOWED_ATTR : SAFE_RICH_ATTRS ,
350+ ALLOW_DATA_ATTR : false ,
351+ FORBID_TAGS : [
352+ "style" ,
353+ "script" ,
354+ "iframe" ,
355+ "object" ,
356+ "embed" ,
357+ "svg" ,
358+ "math" ,
359+ ] ,
360+ FORBID_ATTR : [ "style" , "srcset" , "sizes" , "onerror" , "onclick" ] ,
270361 } ) ;
271362
272363 if ( isInline ) {
0 commit comments