diff --git a/test/cases/components/Markdown/utils.test.ts b/test/cases/components/Markdown/utils.test.ts index 53b73fc3e..9dbcbc558 100644 --- a/test/cases/components/Markdown/utils.test.ts +++ b/test/cases/components/Markdown/utils.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { mdTextFormat, CodeClassNameEnum } from '@/components/Markdown/utils'; +import { mdTextFormat, CodeClassNameEnum, filterSafeProps } from '@/components/Markdown/utils'; describe('Markdown utils', () => { describe('mdTextFormat', () => { @@ -56,4 +56,121 @@ describe('Markdown utils', () => { expect(CodeClassNameEnum.audio).toBe('audio'); }); }); + + describe('filterSafeProps', () => { + const allowedAttrs = new Set(['class', 'style', 'title', 'id']); + + it('should filter out non-whitelisted attributes', () => { + const props = { + class: 'test', + nonexistent: 'value', + title: 'title' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'test', + title: 'title' + }); + }); + + it('should filter out dangerous event handlers', () => { + const props = { + class: 'test', + onClick: () => {}, + onMouseover: () => {} + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'test' + }); + }); + + it('should filter out dangerous protocols', () => { + const props = { + title: 'javascript:alert(1)', + id: 'vbscript:alert(1)', + class: 'safe' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'safe' + }); + }); + + it('should handle encoded malicious content', () => { + const props = { + title: 'javascript:alert(1)', + id: '%6A%61%76%61%73%63%72%69%70%74%3Aalert(1)', + class: 'safe' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'safe' + }); + }); + + it('should filter style objects', () => { + const props = { + style: { + color: 'red', + background: 'javascript:alert(1)' + }, + class: 'test' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'test' + }); + }); + + it('should handle empty and null values', () => { + const props = { + class: '', + title: null, + style: null + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: '', + title: null, + style: null + }); + }); + + it('should filter nested objects except style', () => { + const props = { + data: { key: 'value' }, + style: { color: 'red' }, + class: 'test' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + style: { color: 'red' }, + class: 'test' + }); + }); + + it('should handle multiple iterations of encoded content', () => { + const props = { + title: encodeURIComponent(encodeURIComponent('javascript:alert(1)')), + class: 'safe' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'safe' + }); + }); + + it('should filter suspicious content patterns', () => { + const props = { + title: 'Function("alert(1)")', + id: 'eval("alert(1)")', + class: 'test' + }; + const result = filterSafeProps(props, allowedAttrs); + expect(result).toEqual({ + class: 'test' + }); + }); + }); });