Skip to content

Commit 51c0960

Browse files
committed
fix: RT-360- VAPT malicious src urls
1 parent 3ea05b3 commit 51c0960

File tree

5 files changed

+139
-3
lines changed

5 files changed

+139
-3
lines changed

package-lock.json

Lines changed: 31 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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
},
5050
"dependencies": {
5151
"array-flat-polyfill": "^1.0.1",
52+
"dompurify": "^3.2.3",
5253
"lodash": "^4.17.21",
5354
"lodash.clonedeep": "^4.5.0",
5455
"lodash.flatten": "^4.4.0",

src/toRedactor.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import kebbab from 'lodash.kebabcase'
22
import isEmpty from 'lodash.isempty'
3-
3+
import DOMPurify from 'dompurify'
44
import {IJsonToHtmlElementTags, IJsonToHtmlOptions, IJsonToHtmlTextTags} from './types'
55
import isPlainObject from 'lodash.isplainobject'
66

@@ -494,6 +494,15 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string
494494
}
495495
figureStyles.fieldsEdited.push(figureStyles.caption)
496496
}
497+
if (jsonValue['type'] === 'social-embeds') {
498+
const sanitizedHTML = DOMPurify.sanitize(allattrs['src'])
499+
const urlMatch:any = sanitizedHTML.match(/https?:\/\/[^\s"'>]+/);
500+
if (urlMatch && urlMatch[0] !== 'undefined') {
501+
attrsJson['src'] = decodeURIComponent(urlMatch[0])
502+
} else{
503+
attrsJson['src'] = " "
504+
}
505+
}
497506
if(!(options?.customElementTypes && !isEmpty(options.customElementTypes) && options.customElementTypes[jsonValue['type']])) {
498507
delete attrsJson['url']
499508
}

test/expectedJson.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,83 @@ export default {
19991999
}
20002000
],
20012001
"htmlUpdated": "<p></p><img asset_uid=\"blt5523ee02703e39f5\" src=\"https://images.com/captain_pardip.jpg\" width=\"24.193548387096776\" height=\"auto\" style=\"width: 24.193548387096776%; height: auto;height: auto;\" type=\"asset\" sys-style-type=\"download\"/><p></p><iframe src=\"https://www.***REMOVED***.com/embed/CSvFpBOe8eY\"></iframe><img asset_uid=\"blta2aad0332073026c\" src=\"https://images.com/logo_1.jpg\" height=\"auto\" type=\"asset\" sys-style-type=\"download\"/>"
2002+
},
2003+
"RT-360":{
2004+
"html": [
2005+
`<iframe src="https://www.youtube.com/embed/VD6xJq8NguY" width="560" height="320" data-type="social-embeds" ></iframe>`,
2006+
`<iframe src=" " width="560" height="320" data-type="social-embeds" ></iframe>`,
2007+
'<iframe src=" " width="560" height="320" data-type="social-embeds" ></iframe>',
2008+
],
2009+
"json":
2010+
[
2011+
{
2012+
"type": "doc",
2013+
"attrs": {},
2014+
"uid": "18396bf67f1f4b0a9da57643ac0542ca",
2015+
"children": [
2016+
{
2017+
"uid": "45a850acbeb949db86afe415625ad1ce",
2018+
"type": "social-embeds",
2019+
"attrs": {
2020+
"src": "https://www.youtube.com/embed/VD6xJq8NguY\"></iframe><script>alert(document.cookie)</script><iframe ",
2021+
"width": 560,
2022+
"height": 320
2023+
},
2024+
"children": [
2025+
{
2026+
"text": ""
2027+
}
2028+
]
2029+
}
2030+
],
2031+
"_version": 1
2032+
},
2033+
{
2034+
"type": "doc",
2035+
"attrs": {},
2036+
"uid": "18396bf67f1f4b0a9da57643ac0542ca",
2037+
"children": [
2038+
{
2039+
"uid": "45a850acbeb949db86afe415625ad1ce",
2040+
"type": "social-embeds",
2041+
"attrs": {
2042+
"src": null,
2043+
"width": 560,
2044+
"height": 320
2045+
},
2046+
"children": [
2047+
{
2048+
"text": ""
2049+
}
2050+
]
2051+
}
2052+
],
2053+
"_version": 1
2054+
},
2055+
{
2056+
"type": "doc",
2057+
"attrs": {},
2058+
"uid": "18396bf67f1f4b0a9da57643ac0542ca",
2059+
"children": [
2060+
{
2061+
"uid": "45a850acbeb949db86afe415625ad1ce",
2062+
"type": "social-embeds",
2063+
"attrs": {
2064+
"src": "www.youtube.com/embed/VD6xJq8NguY",
2065+
"width": 560,
2066+
"height": 320
2067+
},
2068+
"children": [
2069+
{
2070+
"text": ""
2071+
}
2072+
]
2073+
}
2074+
],
2075+
"_version": 1
2076+
}
2077+
]
2078+
20022079
}
20032080

20042081
}

test/toRedactor.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,5 +248,25 @@ describe("Testing json to html conversion", () => {
248248
const html = toRedactor(json);
249249
expect(html).toBe(`<iframe src="https://www.***REMOVED***.com/embed/3V-Sq7_uHXQ" width="560" height="320" data-type="social-embeds" ></iframe>`);
250250
})
251+
252+
describe("RT-360", () =>{
253+
it("should remove script and/or other tags from src links in HTML for social-embeds", () => {
254+
const json = expectedValue["RT-360"].json[0]
255+
const html = toRedactor(json);
256+
expect(html).toBe(expectedValue["RT-360"].html[0]);
257+
})
258+
259+
it("should handle undefined or null cases",()=>{
260+
const json = expectedValue["RT-360"].json[1]
261+
const html = toRedactor(json);
262+
expect(html).toBe(expectedValue["RT-360"].html[1]);
263+
})
264+
265+
it("should handle src without protocol",()=>{
266+
const json = expectedValue["RT-360"].json[2]
267+
const html = toRedactor(json);
268+
expect(html).toBe(expectedValue["RT-360"].html[2]);
269+
})
270+
})
251271
})
252272

0 commit comments

Comments
 (0)