From 0ae552102a76f13bbaf36b956650996e6e41989c Mon Sep 17 00:00:00 2001 From: emilielr Date: Thu, 16 Jan 2025 13:46:47 +0100 Subject: [PATCH 1/7] chore(): remove unused inline styling props --- tavla/src/Board/scenarios/Board/index.tsx | 6 +----- tavla/src/Shared/components/Header/index.tsx | 10 +--------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tavla/src/Board/scenarios/Board/index.tsx b/tavla/src/Board/scenarios/Board/index.tsx index a3b835d5e..96b60f85e 100644 --- a/tavla/src/Board/scenarios/Board/index.tsx +++ b/tavla/src/Board/scenarios/Board/index.tsx @@ -4,7 +4,6 @@ import { StopPlaceTile } from '../StopPlaceTile' import { QuayTile } from '../QuayTile' import { Tile } from 'components/Tile' import { defaultFontSize, getFontScale } from 'Board/scenarios/Board/utils' -import { CSSProperties } from 'react' function BoardTile({ tileSpec }: { tileSpec: TTile }) { switch (tileSpec.type) { @@ -15,7 +14,7 @@ function BoardTile({ tileSpec }: { tileSpec: TTile }) { } } -function Board({ board, style }: { board: TBoard; style?: CSSProperties }) { +function Board({ board }: { board: TBoard }) { if (!board.tiles || !board.tiles.length) return ( @@ -28,9 +27,6 @@ function Board({ board, style }: { board: TBoard; style?: CSSProperties }) { className={`max-sm:overflow-y-scroll grid grid-cols-auto-fit-minmax gap-2.5 h-full overflow-hidden supports-[not(display:grid)]:flex supports-[not(display:grid)]:*:m-2.5 ${getFontScale( board.meta?.fontSize || defaultFontSize(board), )} `} - style={{ - ...style, - }} > {board.tiles.map((tile, index) => { return diff --git a/tavla/src/Shared/components/Header/index.tsx b/tavla/src/Shared/components/Header/index.tsx index d323c5b4b..a3cbe089a 100644 --- a/tavla/src/Shared/components/Header/index.tsx +++ b/tavla/src/Shared/components/Header/index.tsx @@ -3,26 +3,18 @@ import TavlaLogoBlue from 'assets/logos/Tavla-blue.svg' import Image from 'next/image' import { TLogo, TTheme } from 'types/settings' import { Clock } from 'components/Clock' -import classNames from 'classnames' function Header({ theme, - className, organizationLogo, }: { theme?: TTheme - className?: string organizationLogo?: TLogo | null }) { const tavlaLogo = theme === 'light' ? TavlaLogoBlue : TavlaLogoWhite return ( -
+
Date: Thu, 16 Jan 2025 13:55:49 +0100 Subject: [PATCH 2/7] feat(security): add security headers --- tavla/next.config.js | 50 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tavla/next.config.js b/tavla/next.config.js index f58224e75..5db3b10c1 100644 --- a/tavla/next.config.js +++ b/tavla/next.config.js @@ -1,6 +1,10 @@ const { PHASE_DEVELOPMENT_SERVER } = require('next/constants') const { withSentryConfig } = require("@sentry/nextjs"); +const cspHeader = ` + frame-ancestors 'none'; +` + /** @type {import('next').NextConfig} */ const nextConfig = { output: 'standalone', @@ -21,11 +25,55 @@ const nextConfig = { }, ], dangerouslyAllowSVG: true, - contentDispositionType: 'attachment', + contentDispositionType: 'attachment', contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, + async headers() { + return [ + { + source: '/(.*)?', + headers: [ + { + key: 'Strict-Transport-Security', + value: 'max-age=63072000; includeSubDomains; preload' + }, + { + key: 'Content-Security-Policy', + value: cspHeader.replace(/\n/g, ''), + }, + { + key: 'X-Content-Type-Options', + value: 'nosniff' + }, + { + key: 'Referrer-Policy', + value: 'strict-origin-when-cross-origin' + }, + ] + }, + { + source: '/:id(\\w{20})', + headers: [ + { + key: 'Strict-Transport-Security', + value: 'max-age=63072000; includeSubDomains; preload' + }, + { + key: 'X-Content-Type-Options', + value: 'nosniff' + }, + { + key: 'Referrer-Policy', + value: 'strict-origin-when-cross-origin' + }, + ] + }, + ] + } } + + module.exports = async (phase, { defaultConfig }) => { if (phase === PHASE_DEVELOPMENT_SERVER) { nextConfig.images.remotePatterns.push({ From ec0e87b7e443d173e1b54c727df2b5b4f1dd158f Mon Sep 17 00:00:00 2001 From: emilielr Date: Mon, 20 Jan 2025 12:51:54 +0100 Subject: [PATCH 3/7] fix(security): set empty csp on tavlevsining --- tavla/next.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tavla/next.config.js b/tavla/next.config.js index 5db3b10c1..56d57672d 100644 --- a/tavla/next.config.js +++ b/tavla/next.config.js @@ -58,6 +58,10 @@ const nextConfig = { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' }, + { + key: 'Content-Security-Policy', + value: '', + }, { key: 'X-Content-Type-Options', value: 'nosniff' From 916e01bd99e18a95cb32a3595250dbfd89ec6f0f Mon Sep 17 00:00:00 2001 From: emilielr Date: Mon, 20 Jan 2025 13:44:52 +0100 Subject: [PATCH 4/7] feat(security): add csp headers --- tavla/next.config.js | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/tavla/next.config.js b/tavla/next.config.js index 56d57672d..2db5c8914 100644 --- a/tavla/next.config.js +++ b/tavla/next.config.js @@ -1,8 +1,37 @@ const { PHASE_DEVELOPMENT_SERVER } = require('next/constants') const { withSentryConfig } = require("@sentry/nextjs"); -const cspHeader = ` +const connectSrc = [ + "'self'", + "https://ws.geonorge.no", + "https://*.posthog.com", + "https://api.entur.io", + "https://*.googleapis.com", + "https://www.google.com" +]; + +if (process.env.NODE_ENV == 'development') { + connectSrc.push("http://*.identitytoolkit.googleapis.com http://127.0.0.1:9099") +} + +const cspHeaderCommon = ` + default-src 'self'; + style-src 'self' 'unsafe-inline'; + script-src 'self' 'unsafe-inline' 'unsafe-eval'; + object-src 'none'; + base-uri 'self'; + form-action 'self'; +` + +const cspHeaderAdmin = ` + connect-src ${connectSrc.join(' ')}; frame-ancestors 'none'; + ${cspHeaderCommon} +` + +const cspHeaderTavlevisning = ` + connect-src 'self' https://api.entur.io; + ${cspHeaderCommon} ` /** @type {import('next').NextConfig} */ @@ -39,7 +68,7 @@ const nextConfig = { }, { key: 'Content-Security-Policy', - value: cspHeader.replace(/\n/g, ''), + value: cspHeaderAdmin.replace(/\n/g, '') }, { key: 'X-Content-Type-Options', @@ -60,7 +89,7 @@ const nextConfig = { }, { key: 'Content-Security-Policy', - value: '', + value: cspHeaderTavlevisning.replace(/\n/g, ''), }, { key: 'X-Content-Type-Options', From a69e86d790a673fdebaee1b97fa1096f00c693f8 Mon Sep 17 00:00:00 2001 From: emilielr Date: Mon, 20 Jan 2025 13:49:08 +0100 Subject: [PATCH 5/7] chore(): remove unused code and inline styling --- .../app/components/PreviewCarousel/index.tsx | 2 +- tavla/src/Shared/components/SecondaryLink.tsx | 26 ------------------- 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 tavla/src/Shared/components/SecondaryLink.tsx diff --git a/tavla/app/components/PreviewCarousel/index.tsx b/tavla/app/components/PreviewCarousel/index.tsx index 18dc488ce..9b9920da4 100644 --- a/tavla/app/components/PreviewCarousel/index.tsx +++ b/tavla/app/components/PreviewCarousel/index.tsx @@ -76,7 +76,7 @@ function PreviewCarousel({ boards }: { boards: TBoard[] }) { data-theme={currentBoard.theme ?? 'dark'} >
- {text} - {external ? : } - - ) -} - -export { SecondaryLink } From 78c74de959fcbaef2566d4a311884e36eeede5ab Mon Sep 17 00:00:00 2001 From: emilielr Date: Wed, 22 Jan 2025 15:52:33 +0100 Subject: [PATCH 6/7] feat(security): add url to connect src and working on chrome 56 --- tavla/next.config.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tavla/next.config.js b/tavla/next.config.js index 2db5c8914..00895d1d4 100644 --- a/tavla/next.config.js +++ b/tavla/next.config.js @@ -1,17 +1,15 @@ const { PHASE_DEVELOPMENT_SERVER } = require('next/constants') const { withSentryConfig } = require("@sentry/nextjs"); -const connectSrc = [ +const commonConnectSrc = [ "'self'", - "https://ws.geonorge.no", - "https://*.posthog.com", "https://api.entur.io", - "https://*.googleapis.com", - "https://www.google.com" -]; + "https://tavla-api.entur.no", + "https://tavla-api.dev.entur.no" +] if (process.env.NODE_ENV == 'development') { - connectSrc.push("http://*.identitytoolkit.googleapis.com http://127.0.0.1:9099") + commonConnectSrc.push("http://*.identitytoolkit.googleapis.com http://127.0.0.1:9099 ws://localhost:3000") } const cspHeaderCommon = ` @@ -23,14 +21,14 @@ const cspHeaderCommon = ` form-action 'self'; ` -const cspHeaderAdmin = ` - connect-src ${connectSrc.join(' ')}; +const cspHeader = ` + connect-src ${commonConnectSrc.join(' ')} https://ws.geonorge.no https://*.posthog.com https://*.googleapis.com https://www.google.com; frame-ancestors 'none'; ${cspHeaderCommon} ` const cspHeaderTavlevisning = ` - connect-src 'self' https://api.entur.io; + connect-src ${commonConnectSrc.join(' ')}; ${cspHeaderCommon} ` @@ -68,7 +66,7 @@ const nextConfig = { }, { key: 'Content-Security-Policy', - value: cspHeaderAdmin.replace(/\n/g, '') + value: cspHeader.replace(/\n/g, '') }, { key: 'X-Content-Type-Options', From f3f643bef81455d8cd59b36f69666f8a59cacf90 Mon Sep 17 00:00:00 2001 From: emilielr Date: Thu, 23 Jan 2025 12:59:38 +0100 Subject: [PATCH 7/7] fix(security): allow backend to connect locally --- tavla/next.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tavla/next.config.js b/tavla/next.config.js index 00895d1d4..d85eb9d00 100644 --- a/tavla/next.config.js +++ b/tavla/next.config.js @@ -9,7 +9,7 @@ const commonConnectSrc = [ ] if (process.env.NODE_ENV == 'development') { - commonConnectSrc.push("http://*.identitytoolkit.googleapis.com http://127.0.0.1:9099 ws://localhost:3000") + commonConnectSrc.push("http://*.identitytoolkit.googleapis.com http://127.0.0.1:9099 ws://localhost:3000 http://127.0.0.1:3001") } const cspHeaderCommon = `