From ae3cf31700086c0cbccfa738d09377a287200c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cintia=20S=C3=A1nchez=20Garc=C3=ADa?= Date: Thu, 20 Oct 2022 10:40:16 +0200 Subject: [PATCH] Address some security vulnerabilities in frontend (#2435) Signed-off-by: Cintia Sanchez Garcia --- .github/codeql/codeql-config.yml | 2 + .github/workflows/codeql-analysis.yml | 1 + web/src/context/AppCtx.tsx | 18 +-- web/src/layout/App.tsx | 104 ++++++++++-------- web/src/layout/common/AnchorHeader.test.tsx | 25 ++++- web/src/layout/common/AnchorHeader.tsx | 10 +- web/src/layout/package/readme/TOC.test.tsx | 37 ++++++- .../layout/package/readme/TOCEntry.test.tsx | 25 ++++- web/src/layout/package/readme/TOCEntry.tsx | 9 +- .../layout/package/readme/TOCList.test.tsx | 13 ++- web/src/layout/stats/index.test.tsx | 29 +++-- web/src/utils/history.test.tsx | 6 +- web/src/utils/history.ts | 6 +- 13 files changed, 194 insertions(+), 91 deletions(-) create mode 100644 .github/codeql/codeql-config.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 00000000..97f95be7 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,2 @@ +paths-ignore: + - docs/api/*.js diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ec3cdae2..b2c3f32b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,6 +22,7 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml - name: Autobuild uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis diff --git a/web/src/context/AppCtx.tsx b/web/src/context/AppCtx.tsx index 3be2b323..6c4b4cc1 100644 --- a/web/src/context/AppCtx.tsx +++ b/web/src/context/AppCtx.tsx @@ -7,7 +7,7 @@ import useSystemThemeMode from '../hooks/useSystemThemeMode'; import { Prefs, Profile, ThemePrefs, UserFullName } from '../types'; import cleanLoginUrlParams from '../utils/cleanLoginUrlParams'; import detectActiveThemeMode from '../utils/detectActiveThemeMode'; -import history from '../utils/history'; +import browserHistory from '../utils/history'; import isControlPanelSectionAvailable from '../utils/isControlPanelSectionAvailable'; import lsPreferences from '../utils/localStoragePreferences'; import lsStorage from '../utils/localStoragePreferences'; @@ -92,16 +92,20 @@ export async function refreshUserProfile(dispatch: Dispatch, redirectUrl?: }`; if (!isUndefined(redirectUrl)) { if (redirectUrl === currentUrl) { - history.replace(redirectUrl); + browserHistory.replace(redirectUrl); } else { + const redirection = redirectUrl.split('?'); // Redirect to correct route when necessary - history.push(redirectUrl); + browserHistory.push({ + pathname: redirection[0], + search: !isUndefined(redirection[1]) ? `?${redirection[1]}` : '', + }); } } } catch (err: any) { dispatch({ type: 'signOut' }); if (err.message === 'invalid session') { - history.push( + browserHistory.push( `${window.location.pathname}${ window.location.search === '' ? '?' : `${window.location.search}&` }modal=login&redirect=${encodeURIComponent(`${window.location.pathname}${window.location.search}`)}` @@ -111,10 +115,10 @@ export async function refreshUserProfile(dispatch: Dispatch, redirectUrl?: } function redirectToControlPanel(context: 'user' | 'org') { - if (history.location.pathname.startsWith('/control-panel')) { - const sections = history.location.pathname.split('/'); + if (browserHistory.location.pathname.startsWith('/control-panel')) { + const sections = browserHistory.location.pathname.split('/'); if (!isControlPanelSectionAvailable(context, sections[2], sections[3])) { - history.push('/control-panel/repositories'); + browserHistory.push('/control-panel/repositories'); } } } diff --git a/web/src/layout/App.tsx b/web/src/layout/App.tsx index f4decaa2..3a19a23b 100644 --- a/web/src/layout/App.tsx +++ b/web/src/layout/App.tsx @@ -7,7 +7,7 @@ import { Route, Router, Switch } from 'react-router-dom'; import { AppCtxProvider } from '../context/AppCtx'; import buildSearchParams from '../utils/buildSearchParams'; -import history from '../utils/history'; +import browserHistory from '../utils/history'; import AlertController from './common/AlertController'; import UserNotificationsController from './common/userNotifications'; import ControlPanelView from './controlPanel'; @@ -38,7 +38,7 @@ export default function App() { return ( - +
Skip to Main Content @@ -59,29 +59,37 @@ export default function App() { '/delete-user', ]} exact - render={({ location }) => ( + render={(routeProps) => (
@@ -91,13 +99,13 @@ export default function App() { { - const searchParams = buildSearchParams(location.search); + render={(routeProps: any) => { + const searchParams = buildSearchParams(routeProps.location.search); return ( <> @@ -108,8 +116,10 @@ export default function App() { setIsSearching={setIsSearching} scrollPosition={scrollPosition} setScrollPosition={setScrollPosition} - fromDetail={location.state ? location.state.hasOwnProperty('from-detail') : false} - visibleModal={getQueryParam(location.search, 'modal') || undefined} + fromDetail={ + routeProps.location.state ? routeProps.location.state.hasOwnProperty('from-detail') : false + } + visibleModal={getQueryParam(routeProps.location.search, 'modal') || undefined} />
@@ -120,32 +130,32 @@ export default function App() { { - const state = location.state ? (location.state as Object) : {}; + render={(routeProps) => { + const state = routeProps.location.state ? (routeProps.location.state as Object) : {}; return ( <>
@@ -156,17 +166,17 @@ export default function App() { ( + render={(routeProps) => ( <>