Skip to content

Commit deef4d1

Browse files
authored
Merge pull request #80 from contentstack/next
Next
2 parents 2ccf9b9 + af913e0 commit deef4d1

File tree

6 files changed

+90
-45
lines changed

6 files changed

+90
-45
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## [1.3.9](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.9) (2024-07-08)
4+
- Fix: SRE vulnerabilities fixed
5+
36
## [1.3.8](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.8) (2024-06-24)
47
- Feat: Support for Image type asset in JsonToHtml
58

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/utils",
3-
"version": "1.3.8",
3+
"version": "1.3.9",
44
"description": "Contentstack utilities for Javascript",
55
"main": "dist/index.es.js",
66
"types": "dist/types/index.d.ts",

src/helper/sanitize.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
type AllowedTags = 'p' | 'a' | 'strong' | 'em' | 'ul' | 'ol' | 'li' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'sub' | 'u' | 'table' | 'thead' | 'tbody' | 'tr' | 'th' | 'td' | 'span'|'fragment'|'strike'|'sup'|'br';
3+
type AllowedAttributes = 'href' | 'title' | 'target' | 'alt' | 'src' | 'class' | 'id' | 'style';
4+
5+
export function sanitizeHTML(input: string, allowedTags: AllowedTags[] = ['p', 'a', 'strong', 'em', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sub', 'u', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'span','fragment','sup','strike','br'], allowedAttributes: AllowedAttributes[] = ['href', 'title', 'target', 'alt', 'src', 'class', 'id', 'style']): string {
6+
// Regular expression to find and remove all HTML tags except the allowed ones
7+
const sanitized = input.replace(/<\/?([a-z][a-z0-9]*)\b[^<>]*>/gi, (match, tag) => {
8+
return allowedTags.includes(tag.toLowerCase()) ? match : '';
9+
});
10+
11+
// Regular expression to remove all attributes except the allowed ones
12+
const cleaned = sanitized.replace(/\s([a-z:]+)=['"][^'"]*['"]/gi
13+
, (match, attribute) => {
14+
return allowedAttributes.includes(attribute.toLowerCase()) ? match : '';
15+
});
16+
17+
return cleaned;
18+
}
19+

src/options/default-node-options.ts

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,77 @@ import { Next, RenderOption } from ".";
22
import MarkType from "../nodes/mark-type";
33
import Node from "../nodes/node";
44
import NodeType from "../nodes/node-type";
5+
import { sanitizeHTML } from "../helper/sanitize";
56

67
export const defaultNodeOption: RenderOption = {
78
[NodeType.DOCUMENT]:(node: Node) => {
89
return ``
910
},
1011
[NodeType.PARAGRAPH]:(node: Node, next: Next) => {
11-
return `<p${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</p>`
12+
return `<p${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</p>`
1213
},
1314
[NodeType.LINK]:(node: Node, next: Next) => {
15+
const sanitizedHref = sanitizeHTML(node.attrs.href || node.attrs.url);
1416
if (node.attrs.target) {
15-
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${node.attrs.href || node.attrs.url}" target="${node.attrs.target}">${next(node.children)}</a>`
17+
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${sanitizedHref}" target="${node.attrs.target}">${sanitizeHTML(next(node.children))}</a>`
1618
}
17-
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${node.attrs.href || node.attrs.url}">${next(node.children)}</a>`
19+
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${sanitizedHref}">${sanitizeHTML(next(node.children))}</a>`
1820
},
1921
[NodeType.IMAGE]:(node: Node, next: Next) => {
20-
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs.src || node.attrs.url}" />${next(node.children)}`
22+
const sanitizedSrc = sanitizeHTML(node.attrs.src || node.attrs.url);
23+
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizedSrc}" />${sanitizeHTML(next(node.children))}`
2124
},
2225
[NodeType.EMBED]:(node: Node, next: Next) => {
23-
return `<iframe${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs.src || node.attrs.url}">${next(node.children)}</iframe>`
26+
const sanitizedSrc = sanitizeHTML(node.attrs.src || node.attrs.url);
27+
return `<iframe${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizedSrc}">${sanitizeHTML(next(node.children))}</iframe>`
2428
},
2529
[NodeType.HEADING_1]:(node: Node, next: Next) => {
26-
return `<h1${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h1>`
30+
return `<h1${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h1>`
2731
},
2832
[NodeType.HEADING_2]:(node: Node, next: Next) => {
29-
return `<h2${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h2>`
33+
return `<h2${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h2>`
3034
},
3135
[NodeType.HEADING_3]:(node: Node, next: Next) => {
32-
return `<h3${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h3>`
36+
return `<h3${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h3>`
3337
},
3438
[NodeType.HEADING_4]:(node: Node, next: Next) => {
35-
return `<h4${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h4>`
39+
return `<h4${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h4>`
3640
},
3741
[NodeType.HEADING_5]:(node: Node, next: Next) => {
38-
return `<h5${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h5>`
42+
return `<h5${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h5>`
3943
},
4044
[NodeType.HEADING_6]:(node: Node, next: Next) => {
41-
return `<h6${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h6>`
45+
return `<h6${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</h6>`
4246
},
4347
[NodeType.ORDER_LIST]:(node: Node, next: Next) => {
44-
return `<ol${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</ol>`
48+
return `<ol${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</ol>`
4549
},
4650
[NodeType.FRAGMENT]:(node: Node, next: Next) => {
47-
return `<fragment>${next(node.children)}</fragment>`
51+
return `<fragment>${sanitizeHTML(next(node.children))}</fragment>`
4852
},
4953
[NodeType.UNORDER_LIST]:(node: Node, next: Next) => {
50-
return `<ul${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</ul>`
54+
return `<ul${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</ul>`
5155
},
5256
[NodeType.LIST_ITEM]:(node: Node, next: Next) => {
53-
return `<li${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</li>`
57+
return `<li${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</li>`
5458
},
5559
[NodeType.HR]:(node: Node, next: Next) => {
5660
return `<hr>`
5761
},
5862
[NodeType.TABLE]:(node: Node, next: Next) => {
59-
return `<table${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</table>`
63+
return `<table${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</table>`
6064
},
6165
[NodeType.TABLE_HEADER]:(node: Node, next: Next) => {
62-
return `<thead${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</thead>`
66+
return `<thead${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</thead>`
6367
},
6468
[NodeType.TABLE_BODY]:(node: Node, next: Next) => {
65-
return `<tbody${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tbody>`
69+
return `<tbody${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</tbody>`
6670
},
6771
[NodeType.TABLE_FOOTER]:(node: Node, next: Next) => {
68-
return `<tfoot${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tfoot>`
72+
return `<tfoot${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</tfoot>`
6973
},
7074
[NodeType.TABLE_ROW]:(node: Node, next: Next) => {
71-
return `<tr${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tr>`
75+
return `<tr${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</tr>`
7276
},
7377
[NodeType.TABLE_HEAD]:(node: Node, next: Next) => {
7478
if (node.attrs.void) return '';
@@ -78,7 +82,7 @@ export const defaultNodeOption: RenderOption = {
7882
`${node.attrs.colSpan ? ` colspan="${node.attrs.colSpan}"` : ``}` +
7983
`${node.attrs.style ? ` style="${node.attrs.style}"` : ``}`+
8084
`${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}`+
81-
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}` +
85+
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}` +
8286
`</th>`
8387
},
8488
[NodeType.TABLE_DATA]:(node: Node, next: Next) => {
@@ -89,52 +93,52 @@ export const defaultNodeOption: RenderOption = {
8993
`${node.attrs.colSpan ? ` colspan="${node.attrs.colSpan}"` : ``}` +
9094
`${node.attrs.style ? ` style="${node.attrs.style}"` : ``}`+
9195
`${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}`+
92-
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}` +
96+
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}` +
9397
`</td>`
9498
},
9599
[NodeType.BLOCK_QUOTE]:(node: Node, next: Next) => {
96-
return `<blockquote${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</blockquote>`
100+
return `<blockquote${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</blockquote>`
97101
},
98102
[NodeType.CODE]:(node: Node, next: Next) => {
99-
return `<code${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</code>`
103+
return `<code${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</code>`
100104
},
101105

102106
['reference']:(node: Node, next: Next) => {
103107
if (node.attrs.type === 'asset') {
104-
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs['asset-link']}" />`
108+
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${sanitizeHTML(node.attrs['class-name'])}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizeHTML(node.attrs['asset-link'])}" />`
105109
}
106110
return ``
107111
},
108112
['default']:(node: Node, next: Next) => {
109-
return next(node.children)
113+
return sanitizeHTML(next(node.children))
110114
},
111115

112116
[MarkType.BOLD]:(text: string) => {
113-
return `<strong>${text}</strong>`
117+
return `<strong>${sanitizeHTML(text)}</strong>`
114118
},
115119
[MarkType.ITALIC]:(text: string) => {
116-
return `<em>${text}</em>`
120+
return `<em>${sanitizeHTML(text)}</em>`
117121
},
118122
[MarkType.UNDERLINE]:(text: string) => {
119-
return `<u>${text}</u>`
123+
return `<u>${sanitizeHTML(text)}</u>`
120124
},
121125
[MarkType.STRIKE_THROUGH]:(text: string) => {
122-
return `<strike>${text}</strike>`
126+
return `<strike>${sanitizeHTML(text)}</strike>`
123127
},
124128
[MarkType.INLINE_CODE]:(text: string) => {
125-
return `<span>${text}</span>`
129+
return `<span>${sanitizeHTML(text)}</span>`
126130
},
127131
[MarkType.SUBSCRIPT]:(text: string) => {
128-
return `<sub>${text}</sub>`
132+
return `<sub>${sanitizeHTML(text)}</sub>`
129133
},
130134
[MarkType.SUPERSCRIPT]:(text: string) => {
131-
return `<sup>${text}</sup>`
135+
return `<sup>${sanitizeHTML(text)}</sup>`
132136
},
133137
[MarkType.BREAK]:(text: string) => {
134-
return `<br />${text}`
138+
return `<br />${sanitizeHTML(text)}`
135139
},
136140
[MarkType.CLASSNAME_OR_ID]:(text: string, classname: string, id:string) => {
137-
return `<span${classname ? ` class="${classname}"` : ``}${id ? ` id="${id}"` : ``}>${text}</span>`
141+
return `<span${classname ? ` class="${classname}"` : ``}${id ? ` id="${id}"` : ``}>${sanitizeHTML(text)}</span>`
138142
}
139143

140144
}

0 commit comments

Comments
 (0)