Skip to content

Commit 1b83dcd

Browse files
Merge pull request #76 from contentstack/RT-360
feat: handle invalid attr key-values
2 parents 500508f + 16d29e6 commit 1b83dcd

File tree

6 files changed

+63
-3
lines changed

6 files changed

+63
-3
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,35 @@ To help the JSON RTE Serializer recognize and process additional tags that are c
365365

366366
### Convert JSON to HTML
367367

368+
#### HTML Attribute Name and Value Sanitization
369+
370+
371+
This project ensures that HTML attributes are properly validated and sanitized according to the W3C HTML specification. It validates attribute names based on the HTML standards and sanitizes attribute values to ensure correct rendering and security, particularly against cross-site scripting (XSS) vulnerabilities.
372+
373+
#### Attribute Name Guidelines
374+
375+
All HTML attribute names must conform to the [W3C HTML specification](https://www.w3.org/TR/2012/WD-html-markup-20120329/syntax.html#attribute-name). These guidelines specify the following rules:
376+
377+
- **Printable ASCII Characters:** Attribute names must consist only of printable ASCII characters.
378+
- **Case-Insensitive:** Attribute names are case-insensitive, but lowercase is preferred for consistency.
379+
- **No Special Characters:** Attribute names cannot contain spaces or special characters such as `=`, `>`, `<`, `"`, etc.
380+
- **Allowed Attributes:** Attributes such as `xmlns`, `aria-*`, `data-*`, and others defined by HTML5 standards are allowed and must follow specific rules.
381+
382+
##### Important Note:
383+
If an attribute name does not conform to these rules, the attribute will be **dropped** from the element.
384+
385+
#### Attribute Value Guidelines
386+
387+
The values of HTML attributes are sanitized to ensure proper rendering and to mitigate security risks, such as Cross-Site Scripting (XSS). This sanitization process involves replacing HTML entities (like `&lt;`, `&gt;`, `&amp;`, etc.) with their corresponding characters and removing any invalid or unsafe characters.
388+
389+
Here are some common HTML entities and their replacements:
390+
391+
- `&lt;``<`
392+
- `&gt;``>`
393+
- `&amp;``&`
394+
395+
396+
<hr>
368397
You can pass the `allowNonStandardTags: true` parameter within the `jsonToHtml` method to allow the JSON RTE Serializer tool to recognize standard HTML tags or element types and convert them into JSON format.
369398

370399
You can use the following customized JSON RTE Serializer code to convert your JSON RTE field data into HTML format.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/json-rte-serializer",
3-
"version": "2.0.13",
3+
"version": "2.1.0",
44
"description": "This Package converts Html Document to Json and vice-versa.",
55
"main": "lib/index.js",
66
"module": "lib/index.mjs",

src/toRedactor.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import kebbab from 'lodash.kebabcase'
22
import isEmpty from 'lodash.isempty'
33
import {IJsonToHtmlElementTags, IJsonToHtmlOptions, IJsonToHtmlTextTags} from './types'
44
import isPlainObject from 'lodash.isplainobject'
5-
import {replaceHtmlEntities } from './utils'
5+
import {replaceHtmlEntities, forbiddenAttrChars } from './utils'
66

77
const ELEMENT_TYPES: IJsonToHtmlElementTags = {
88
'blockquote': (attrs: string, child: string) => {
@@ -507,6 +507,9 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string
507507
}
508508
delete attrsJson['redactor-attributes']
509509
Object.entries(attrsJson).forEach((key) => {
510+
if (forbiddenAttrChars.some(char => key[0].includes(char))) {
511+
return;
512+
}
510513
return key[1] ? (key[1] !== '' ? (attrs += `${key[0]}="${replaceHtmlEntities(key[1])}" `) : '') : ''
511514
})
512515
attrs = (attrs.trim() ? ' ' : '') + attrs.trim()

src/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ export function replaceHtmlEntities(str: string): string {
55
.replace(/>/g, '&gt;')
66
.replace(/"/g, '&quot;');
77
}
8+
9+
export const forbiddenAttrChars = ['"', "'", '>','<', '/', '='];

test/expectedJson.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,8 @@ export default {
20062006
`<iframe width="560" height="320" data-type="social-embeds" ></iframe><iframe allowfullscreen=\"true\"></iframe>`,
20072007
'<iframe src=\"www.youtube.com/watch?v=Gw7EqoOYC9A\" width=\"560\" height=\"320\" data-type=\"social-embeds\" ></iframe><iframe allowfullscreen=\"true\" src=\"www.youtube.com/embed/VD6xJq8NguY\"></iframe>',
20082008
`<iframe src=\"https://www.youtube.com/embed/Gw7EqoOYC9A?si=bWdnezma6qFAePQU\" width=\"560\" height=\"320\" data-type=\"social-embeds\" ></iframe><iframe allowfullscreen=\"true\" src=\"https://www.youtube.com/embed/Gw7EqoOYC9A?si=bWdnezma6qFAePQU\"></iframe>`,
2009-
`<iframe src="null" width="560" height="320" title=" This is for &lt;/p&gt;testing &lt;/p&gt; purpose 'only' " data-type="social-embeds" ></iframe>`
2009+
`<iframe src="null" width="560" height="320" title=" This is for &lt;/p&gt;testing &lt;/p&gt; purpose 'only' " data-type="social-embeds" ></iframe>`,
2010+
`<iframe 123="456" src="https://www.youtube.com/embed/Gw7EqoOYC9A?si=bWdnezma6qFAePQU" width="560" height="320" status="Active" data-type="social-embeds" ></iframe>`
20102011
],
20112012
"json":
20122013
[
@@ -2181,6 +2182,25 @@ export default {
21812182
},
21822183
children: [{ text: "" }],
21832184
},
2185+
{
2186+
"uid": "45a850acbeb949db86afe415625ad1ce",
2187+
"type": "social-embeds",
2188+
"attrs": {
2189+
"123": "456",
2190+
"src": "https://www.youtube.com/embed/Gw7EqoOYC9A?si=bWdnezma6qFAePQU",
2191+
"width": 560,
2192+
"height": 320,
2193+
"<p>ding": 234,
2194+
"status": "Active",
2195+
"emptyKey<": "12",
2196+
"country/": "USA"
2197+
},
2198+
"children": [
2199+
{
2200+
"text": ""
2201+
}
2202+
]
2203+
},
21842204

21852205
]
21862206

test/toRedactor.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,12 @@ describe("Testing json to html conversion", () => {
279279
const html = toRedactor(json);
280280
expect(html).toBe(expectedValue["RT-360"].html[4]);
281281
})
282+
283+
it("should drop invalid attribute names",()=>{
284+
const json = expectedValue["RT-360"].json[5]
285+
const html = toRedactor(json);
286+
expect(html).toBe(expectedValue["RT-360"].html[5]);
287+
})
282288
})
283289

284290
test('should convert numeric width to string', () => {

0 commit comments

Comments
 (0)