diff --git a/src/server/routes/contentful.js b/src/server/routes/contentful.js index 1084af62b..b61469b9c 100644 --- a/src/server/routes/contentful.js +++ b/src/server/routes/contentful.js @@ -12,6 +12,7 @@ import { getService, getSpaceId, articleVote, + ALLOWED_DOMAINS, } from '../services/contentful'; const cors = require('cors'); @@ -37,7 +38,11 @@ routes.use( version, } = req.params; const spaceId = getSpaceId(spaceName); - res.redirect(`https://${ASSETS_DOMAIN}/spaces/${spaceId}/environments/${environment}/${id}/${version}/${name}`); + if (!ALLOWED_DOMAINS.includes(ASSETS_DOMAIN)) { + throw new Error('Invalid domain detected!'); + } + const url = new URL(`https://${ASSETS_DOMAIN}/spaces/${spaceId}/environments/${environment}/${id}/${version}/${name}`); + res.redirect(url.href); }, ); @@ -52,8 +57,12 @@ routes.use( spaceName, version, } = req.params; + if (!ALLOWED_DOMAINS.includes(IMAGES_DOMAIN)) { + throw new Error('Invalid domain detected!'); + } const spaceId = getSpaceId(spaceName); - res.redirect(`https://${IMAGES_DOMAIN}/spaces/${spaceId}/environments/${environment}/${id}/${version}/${name}`); + const url = new URL(`https://${IMAGES_DOMAIN}/spaces/${spaceId}/environments/${environment}/${id}/${version}/${name}`); + res.redirect(url.href); }, ); diff --git a/src/server/services/contentful.js b/src/server/services/contentful.js index 2525696f3..1091759c5 100644 --- a/src/server/services/contentful.js +++ b/src/server/services/contentful.js @@ -21,6 +21,7 @@ const PREVIEW_URL = 'https://preview.contentful.com/spaces'; export const ASSETS_DOMAIN = 'assets.ctfassets.net'; export const IMAGES_DOMAIN = 'images.ctfassets.net'; +export const ALLOWED_DOMAINS = [ASSETS_DOMAIN, IMAGES_DOMAIN]; const MAX_FETCH_RETRIES = 5; /** diff --git a/src/shared/components/TopcoderHeader/index.jsx b/src/shared/components/TopcoderHeader/index.jsx index 5e8f5d73f..761d17d4f 100644 --- a/src/shared/components/TopcoderHeader/index.jsx +++ b/src/shared/components/TopcoderHeader/index.jsx @@ -44,6 +44,7 @@ import './style.scss'; /* global window, document */ const BASE_URL = config.URL.BASE; +const VALID_BASE_URLS = ['https://www.topcoder-dev.com', 'https://www.topcoder.com']; const MENU = [{ title: 'Compete', @@ -426,9 +427,13 @@ export default class TopcoderHeader extends React.Component { ref={(input) => { this.searchInput = input; }} onKeyPress={(event) => { if (event.key === 'Enter') { - window.location = `${BASE_URL}/search/members?q=${ - encodeURIComponent(event.target.value) - }`; + if (!VALID_BASE_URLS.includes(BASE_URL)) { + return; + } + const query = event.target.value.trim(); + const url = new URL(`${BASE_URL}/search/members`); + url.searchParams.append('q', query); + window.location = url.href; } }} onBlur={closeSearch}