Skip to content

Commit 0ef26b8

Browse files
Merge pull request #7024 from topcoder-platform/PM-198
PM-198 Fix reflected XSS
2 parents 0d1e3c8 + 484fb70 commit 0ef26b8

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@
172172
"url-parse": "^1.4.1",
173173
"uuid": "^3.3.2",
174174
"valid-url": "^1.0.9",
175-
"xml2json": "^0.11.2"
175+
"xml2json": "^0.11.2",
176+
"xss": "^1.0.15"
176177
},
177178
"devDependencies": {
178179
"@commitlint/cli": "^8.3.5",

src/server/services/mmLeaderboard.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Server-side functions necessary for effective integration with MMLeaderboard
44
*/
55
import { services } from 'topcoder-react-lib';
6+
import xss from 'xss';
67

78
const { api, submissions } = services;
89

@@ -17,13 +18,14 @@ export default class MMLService {
1718
*/
1819
async getLeaderboard(req, res, next) {
1920
try {
21+
const sanitizedId = xss(req.params.id);
2022
const m2mToken = await api.getTcM2mToken();
2123
const subSrv = submissions.getService(m2mToken);
2224
const reviewIds = await subSrv.getScanReviewIds();
2325
const v5api = api.getApiV5(m2mToken);
24-
const subs = await v5api.get(`/submissions?challengeId=${req.params.id}&page=1&perPage=500`);
26+
const subs = await v5api.get(`/submissions?challengeId=${sanitizedId}&page=1&perPage=500`);
2527
return res.send({
26-
id: req.params.id,
28+
id: sanitizedId,
2729
subs: await subs.json(),
2830
reviewIds,
2931
});

src/server/services/recruitCRM.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import qs from 'qs';
77
import _ from 'lodash';
88
import { logger, services } from 'topcoder-react-lib';
99
import Joi from 'joi';
10+
import xss from 'xss';
1011
import { sendEmailDirect } from './sendGrid';
1112
// import GSheetService from './gSheet';
1213

@@ -186,7 +187,12 @@ export default class RecruitCRMService {
186187
*/
187188
async getJob(req, res, next) {
188189
try {
189-
const response = await fetch(`${this.private.baseUrl}/v1/jobs/${req.params.id}`, {
190+
const sanitizedId = xss(req.params.id);
191+
192+
if (!/^[a-zA-Z0-9-_]{8,20}$/.test(sanitizedId)) {
193+
return res.status(400).json({ error: 'Invalid job ID format.' });
194+
}
195+
const response = await fetch(`${this.private.baseUrl}/v1/jobs/${sanitizedId}`, {
190196
method: 'GET',
191197
headers: {
192198
'Content-Type': req.headers['content-type'],
@@ -201,7 +207,7 @@ export default class RecruitCRMService {
201207
const error = {
202208
error: true,
203209
status: response.status,
204-
url: `${this.private.baseUrl}/v1/jobs/${req.params.id}`,
210+
url: `${this.private.baseUrl}/v1/jobs/${sanitizedId}`,
205211
errObj: await response.json(),
206212
};
207213
logger.error(error);

0 commit comments

Comments
 (0)