From 187d56568240a69bb040f7ca26343d426cc99554 Mon Sep 17 00:00:00 2001
From: shanshuirenjia <978987373@qq.com>
Date: Wed, 14 Apr 2021 16:31:48 +0800
Subject: [PATCH] repair notification xss bug
---
frontend/src/components/common/notice-item.js | 79 ++++++++++++++-----
1 file changed, 60 insertions(+), 19 deletions(-)
diff --git a/frontend/src/components/common/notice-item.js b/frontend/src/components/common/notice-item.js
index 303df029d3..3980068696 100644
--- a/frontend/src/components/common/notice-item.js
+++ b/frontend/src/components/common/notice-item.js
@@ -33,6 +33,7 @@ class NoticeItem extends React.Component {
let groupStaff = detail.group_staff_name;
+ // group name does not support special characters
let userHref = siteRoot + 'profile/' + detail.group_staff_email + '/';
let groupHref = siteRoot + 'group/' + detail.group_id + '/';
let groupName = detail.group_name;
@@ -58,15 +59,22 @@ class NoticeItem extends React.Component {
let path = detail.path;
let notice = '';
- let repoLink = '' + repoName + '';
+ // 1. handle translate
if (path === '/') { // share repo
notice = gettext('{share_from} has shared a library named {repo_link} to you.');
} else { // share folder
notice = gettext('{share_from} has shared a folder named {repo_link} to you.');
}
+ // 2. handle xss(cross-site scripting)
notice = notice.replace('{share_from}', shareFrom);
- notice = notice.replace('{repo_link}', repoLink);
+ notice = notice.replace('{repo_link}', `{tagA}${repoName}{/tagA}`);
+ notice = Utils.HTMLescape(notice);
+
+ // 3. add jump link
+ notice = notice.replace('{tagA}', ``);
+ notice = notice.replace('{/tagA}', '');
+
return {avatar_url, notice};
}
@@ -84,16 +92,24 @@ class NoticeItem extends React.Component {
let path = detail.path;
let notice = '';
- let repoLink = '' + repoName + '';
- let groupLink = '' + groupName + '';
+ // 1. handle translate
if (path === '/') {
notice = gettext('{share_from} has shared a library named {repo_link} to group {group_link}.');
} else {
notice = gettext('{share_from} has shared a folder named {repo_link} to group {group_link}.');
}
+
+ // 2. handle xss(cross-site scripting)
notice = notice.replace('{share_from}', shareFrom);
- notice = notice.replace('{repo_link}', repoLink);
- notice = notice.replace('{group_link}', groupLink);
+ notice = notice.replace('{repo_link}', `{tagA}${repoName}{/tagA}`);
+ notice = notice.replace('{group_link}', `{tagB}${groupName}{/tagB}`);
+ notice = Utils.HTMLescape(notice);
+
+ // 3. add jump link
+ notice = notice.replace('{tagA}', ``);
+ notice = notice.replace('{/tagA}', '');
+ notice = notice.replace('{tagB}', ``);
+ notice = notice.replace('{/tagB}', '');
return {avatar_url, notice};
}
@@ -105,32 +121,50 @@ class NoticeItem extends React.Component {
let repoName = detail.repo_name;
let repoUrl = siteRoot + 'library/' + detail.repo_id + '/' + repoName + '/';
+ // 1. handle translate
let notice = gettext('{user} has transfered a library named {repo_link} to you.');
- let repoLink = '' + repoName + '';
+
+ // 2. handle xss(cross-site scripting)
notice = notice.replace('{user}', repoOwner);
- notice = notice.replace('{repo_link}', repoLink);
+ notice = notice.replace('{repo_link}', `{tagA}${repoName}{/tagA}`);
+ notice = Utils.HTMLescape(notice);
+
+ // 3. add jump link
+ notice = notice.replace('{tagA}', ``);
+ notice = notice.replace('{/tagA}', '');
return {avatar_url, notice};
}
if (noticeType === MSG_TYPE_FILE_UPLOADED) {
let avatar_url = detail.uploaded_user_avatar_url;
let fileName = detail.file_name;
- let fileLink = siteRoot + 'lib/' + detail.repo_id + '/' + 'file' + Utils.encodePath(detail.file_path);
+ let fileLink = siteRoot + 'lib/' + detail.repo_id + '/' + 'file' + detail.file_path;
let folderName = detail.folder_name;
- let folderLink = siteRoot + 'library/' + detail.repo_id + '/' + detail.repo_name + Utils.encodePath(detail.folder_path);
+ let folderLink = siteRoot + 'library/' + detail.repo_id + '/' + detail.repo_name + detail.folder_path;
let notice = '';
if (detail.repo_id) { // todo is repo exist ?
- let uploadFileLink = '' + fileName + '';
- let uploadedLink = '' + folderName + '';
+ // 1. handle translate
+ notice = gettext('A file named {upload_file_link} is uploaded to {uploaded_link}.');
- notice = gettext('A file named {upload_file_link} is uploaded to {uploaded_link}.');
- notice = notice.replace('{upload_file_link}', uploadFileLink);
- notice = notice.replace('{uploaded_link}', uploadedLink);
+ // 2. handle xss(cross-site scripting)
+ notice = notice.replace('{upload_file_link}', `{tagA}${fileName}{/tagA}`);
+ notice = notice.replace('{uploaded_link}', `{tagB}${folderName}{/tagB}`);
+ notice = Utils.HTMLescape(notice);
+
+ // 3. add jump link
+ notice = notice.replace('{tagA}', ``);
+ notice = notice.replace('{/tagA}', '');
+ notice = notice.replace('{tagB}', ``);
+ notice = notice.replace('{/tagB}', '');
} else {
+ // 1. handle translate
notice = gettext('A file named {upload_file_link} is uploaded to {uploaded_link}.');
- notice = notice.replace('{upload_file_link}', fileName);
- notice = notice.replace('{uploaded_link}', 'Deleted Library');
+
+ // 2. handle xss(cross-site scripting)
+ notice = notice.replace('{upload_file_link}', `${fileName}`);
+ notice = Utils.HTMLescape(notice);
+ notice = notice.replace('{uploaded_link}', `Deleted Library`);
}
return {avatar_url, notice};
}
@@ -144,10 +178,17 @@ class NoticeItem extends React.Component {
let fileName = detail.file_name;
let fileUrl = siteRoot + 'lib/' + detail.repo_id + '/' + 'file' + detail.file_path;
+ // 1. handle translate
let notice = gettext('File {file_link} has a new comment form user {author}.');
- let fileLink = '' + fileName + '';
- notice = notice.replace('{file_link}', fileLink);
+
+ // 2. handle xss(cross-site scripting)
+ notice = notice.replace('{file_link}', `{tagA}${fileName}{/tagA}`);
notice = notice.replace('{author}', author);
+ notice = Utils.HTMLescape(notice);
+
+ // 3. add jump link
+ notice = notice.replace('{tagA}', ``);
+ notice = notice.replace('{/tagA}', '');
return {avatar_url, notice};
}