diff --git a/package-lock.json b/package-lock.json index f37c9253..42002c51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@tanstack/vue-query": "^5.66.0", "axios": "^1.7.9", "chart.js": "^4.4.7", + "dompurify": "^3.2.4", "js-cookie": "^3.0.5", "pinia": "^2.3.0", "tailwind-scrollbar-hide": "^2.0.0", @@ -22,6 +23,7 @@ }, "devDependencies": { "@tsconfig/node22": "^22.0.0", + "@types/dompurify": "^3.0.5", "@types/js-cookie": "^3.0.6", "@types/node": "^22.10.2", "@typescript-eslint/eslint-plugin": "^8.20.0", @@ -1710,6 +1712,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1741,6 +1753,13 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", @@ -2893,6 +2912,15 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "license": "MIT" }, + "node_modules/dompurify": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/package.json b/package.json index c293994b..40d59880 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@tanstack/vue-query": "^5.66.0", "axios": "^1.7.9", "chart.js": "^4.4.7", + "dompurify": "^3.2.4", "js-cookie": "^3.0.5", "pinia": "^2.3.0", "tailwind-scrollbar-hide": "^2.0.0", @@ -27,6 +28,7 @@ }, "devDependencies": { "@tsconfig/node22": "^22.0.0", + "@types/dompurify": "^3.0.5", "@types/js-cookie": "^3.0.6", "@types/node": "^22.10.2", "@typescript-eslint/eslint-plugin": "^8.20.0", diff --git a/src/App.vue b/src/App.vue index e1ac0e3c..758082b8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -4,6 +4,7 @@ import TheView from './layout/TheView.vue' diff --git a/src/api/admin.ts b/src/api/admin.ts index 7ef09fd7..d58309e6 100644 --- a/src/api/admin.ts +++ b/src/api/admin.ts @@ -1,6 +1,7 @@ import type { NewLabelTypes, UserRegistrationApiProps, UserUpdateValue } from '@/types/admin' import type { LabelDataTypes } from '@/types/common' import { axiosInstance, formDataAxiosInstance } from '@/utils/axios' +import DOMPurify from 'dompurify' export const deleteLabelAdmin = async (id: number) => { const response = await axiosInstance.delete(`/api/managements/labels/${id}`) @@ -14,7 +15,7 @@ export const postAddLabelAdmin = async (newLabel: NewLabelTypes) => { export const patchLabelAdmin = async (editLabel: LabelDataTypes) => { const response = await axiosInstance.patch(`/api/managements/labels/${editLabel.labelId}`, { - labelName: editLabel.labelName, + labelName: DOMPurify.sanitize(editLabel.labelName), labelColor: editLabel.labelColor }) return response.data diff --git a/src/api/user.ts b/src/api/user.ts index bb7ee1de..9624dab4 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,6 +1,7 @@ import type { Status } from '@/types/common' import type { RequestApprovePostTypes } from '@/types/manager' import { axiosInstance, formDataAxiosInstance } from '@/utils/axios' +import DOMPurify from 'dompurify' export const postTaskRequest = async (formdata: FormData) => { const response = await formDataAxiosInstance.post('/api/tasks', formdata) @@ -54,7 +55,9 @@ export const getHistory = async (taskID: number | null) => { } export const postComment = async (taskID: number, content: string) => { - const response = await axiosInstance.post(`/api/tasks/${taskID}/comments`, { content }) + const response = await axiosInstance.post(`/api/tasks/${taskID}/comments`, { + content: DOMPurify.sanitize(content) + }) return response.data } @@ -66,11 +69,6 @@ export const postCommentAttachment = async (taskID: number, formdata: FormData) return response.data } -export const patchComment = async (commentId: number, content: string) => { - const response = await axiosInstance.patch(`/api/comments/${commentId}`, { content }) - return response.data -} - export const deleteComment = async (commentId: number) => { const response = await axiosInstance.delete(`/api/comments/${commentId}`) return response.data diff --git a/src/components/common/EditInformation.vue b/src/components/common/EditInformation.vue index 91b49c41..bd061bdf 100644 --- a/src/components/common/EditInformation.vue +++ b/src/components/common/EditInformation.vue @@ -139,6 +139,8 @@ import FormButtonContainer from './FormButtonContainer.vue' import FormCheckbox from './FormCheckbox.vue' import ImageContainer from './ImageContainer.vue' import ModalView from './ModalView.vue' +import DOMPurify from 'dompurify' + const router = useRouter() const memberStore = useMemberStore() @@ -276,7 +278,7 @@ const handleSubmit = async () => { if (isInvalid.value == false && isFull.value == false) { const formData = new FormData() const memberInfo = { - name: name.value, + name: DOMPurify.sanitize(name.value), isProfileImageDeleted: imageDelete.value, emailNotification: emailCheck.value, kakaoWorkNotification: kakaoWorkCheck.value diff --git a/src/components/common/ModalView.vue b/src/components/common/ModalView.vue index b9c407f9..b69a85c9 100644 --- a/src/components/common/ModalView.vue +++ b/src/components/common/ModalView.vue @@ -1,90 +1,92 @@