feat: 修复xss漏洞

This commit is contained in:
harrywan 2024-10-16 16:06:00 +08:00
parent 831a6c6c6e
commit f01528d4a9
5 changed files with 19 additions and 7 deletions

View File

@ -30,6 +30,7 @@
"peerDependencies": { "peerDependencies": {
"@fesjs/fes": "^3.1.13", "@fesjs/fes": "^3.1.13",
"@fesjs/fes-design": ">=0.7.0", "@fesjs/fes-design": ">=0.7.0",
"dompurify": "^3.1.7",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-router": "^4.0.1" "vue-router": "^4.0.1"
}, },

View File

@ -1,3 +1,5 @@
import DOMPurify from 'dompurify';
const isStr = function (str) { const isStr = function (str) {
return typeof str === 'string'; return typeof str === 'string';
}; };
@ -26,7 +28,7 @@ export function isValid(elm) {
export function validateContent(svgContent) { export function validateContent(svgContent) {
const div = document.createElement('div'); const div = document.createElement('div');
div.innerHTML = svgContent; div.innerHTML = DOMPurify.sanitize(svgContent);
// setup this way to ensure it works on our buddy IE // setup this way to ensure it works on our buddy IE
for (let i = div.childNodes.length - 1; i >= 0; i--) { for (let i = div.childNodes.length - 1; i >= 0; i--) {

View File

@ -1,11 +1,11 @@
<script lang="jsx"> <script lang="jsx">
import { ref, onBeforeMount, isVNode } from 'vue'; import { isVNode, onBeforeMount, ref } from 'vue';
// eslint-disable-next-line import/extensions
import Icons from '../icons'; import Icons from '../icons';
import { validateContent } from '../helpers/svg'; import { validateContent } from '../helpers/svg';
const urlReg = /^((https?|ftp|file):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/; const urlReg = /^((https?|ftp|file):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
const isUrlResource = (name) => urlReg.test(name) || name.includes('.svg'); const isUrlResource = name => urlReg.test(name) || name.includes('.svg');
export default { export default {
props: { props: {
@ -25,7 +25,8 @@ export default {
}); });
} }
}); });
} else { }
else {
AIconComponent.value = Icons[props.icon]; AIconComponent.value = Icons[props.icon];
} }
} }
@ -39,13 +40,14 @@ export default {
return <AIconComponent.value />; return <AIconComponent.value />;
} }
if (AText.value) { if (AText.value) {
return <span class={'fes-layout-icon'} innerHTML={AText.value}></span>; return <span class="fes-layout-icon" innerHTML={AText.value}></span>;
} }
return null; return null;
}; };
}, },
}; };
</script> </script>
<style> <style>
.fes-layout-icon { .fes-layout-icon {
display: inline-block; display: inline-block;

View File

@ -9,7 +9,7 @@ export const beforeRender = {
const { setRole, getRole } = accessApi; const { setRole, getRole } = accessApi;
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(() => { setTimeout(() => {
setRole('menuTest'); setRole('admin');
resolve({ resolve({
userName: '李雷', userName: '李雷',
}); });

7
pnpm-lock.yaml generated
View File

@ -441,6 +441,9 @@ importers:
'@vueuse/core': '@vueuse/core':
specifier: ^10.7.0 specifier: ^10.7.0
version: 10.7.0(vue@3.3.4) version: 10.7.0(vue@3.3.4)
dompurify:
specifier: ^3.1.7
version: 3.1.7
vue: vue:
specifier: ^3.2.47 specifier: ^3.2.47
version: 3.3.4 version: 3.3.4
@ -6980,6 +6983,10 @@ packages:
domelementtype: 2.3.0 domelementtype: 2.3.0
dev: false dev: false
/dompurify@3.1.7:
resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==}
dev: false
/domutils@2.8.0: /domutils@2.8.0:
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
dependencies: dependencies: