From 67b27d49e4513a54c60d6ed44a954eaf63c41641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Sat, 24 Aug 2024 15:45:24 +0200 Subject: [PATCH] feat: configure CSP (#1357) * feat: configure CSP * test: fix Argos CSP --- apps/backend/src/config/index.ts | 8 ++++ apps/backend/src/web/app.ts | 19 ++++++++- package-lock.json | 73 +++++++++++++++++++++++--------- package.json | 2 +- playwright.config.mjs | 10 +++-- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/apps/backend/src/config/index.ts b/apps/backend/src/config/index.ts index d96e388a2..fdb24204a 100644 --- a/apps/backend/src/config/index.ts +++ b/apps/backend/src/config/index.ts @@ -61,6 +61,14 @@ const config = convict({ default: false, }, }, + csp: { + scriptSrc: { + doc: "Content Security Policy script-src", + format: Array, + default: [], + env: "CSP_SCRIPT_SRC", + }, + }, api: { baseUrl: { doc: "The API base URL", diff --git a/apps/backend/src/web/app.ts b/apps/backend/src/web/app.ts index f23af6e56..9ed7e24d6 100644 --- a/apps/backend/src/web/app.ts +++ b/apps/backend/src/web/app.ts @@ -60,7 +60,24 @@ export const createApp = async () => { app.use( helmet({ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - contentSecurityPolicy: false, + contentSecurityPolicy: { + directives: { + "default-src": ["'self'"], + "img-src": [ + "'self'", + "https://argos-ci.com", + "https://github.com", + "https://avatars.githubusercontent.com", + "https://argos.twic.pics", + ], + "script-src": [ + "'self'", + // Script to update color classes + "'sha256-3eiqAvd5lbIOVQdobPBczwuRAhAf7/oxg3HH2aFmp8Y='", + ...config.get("csp.scriptSrc"), + ], + }, + }, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, crossOriginOpenerPolicy: false, diff --git a/package-lock.json b/package-lock.json index 9ed12fbab..5793943e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ ], "devDependencies": { "@0no-co/graphqlsp": "^1.12.13", - "@argos-ci/playwright": "^3.4.1", + "@argos-ci/playwright": "^3.5.0", "@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/client-preset": "^4.3.3", "@graphql-codegen/fragment-matcher": "^5.0.2", @@ -803,10 +803,23 @@ "node": ">=14" } }, + "node_modules/@argos-ci/api-client": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@argos-ci/api-client/-/api-client-0.2.0.tgz", + "integrity": "sha512-stqugeAtbHjD2MwezvgJ4hU0HvlEGwGDVsJvUUD4YoRS0putS8yFjXuempkc90XGeHDEfYZgvG372rcK7/FClA==", + "dev": true, + "license": "MIT", + "dependencies": { + "openapi-fetch": "^0.11.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@argos-ci/browser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@argos-ci/browser/-/browser-2.1.2.tgz", - "integrity": "sha512-4dpz76kW0KnXCYdxtkcdiaYUM4owmKtT9zPqrd1yPo+VuSNCNULyCZJ4mdy0aXWT716JLMMmIZ3AnQSkyaqvaA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@argos-ci/browser/-/browser-2.1.3.tgz", + "integrity": "sha512-C9/k32HrmkHkUT9KrhHuOvlli1ibPGE1nkToC6+t4cAmbJCIU8HFrVa6VG2UT3xJjLht+gpqvPwTbJAsCRXv3A==", "dev": true, "license": "MIT", "engines": { @@ -814,18 +827,19 @@ } }, "node_modules/@argos-ci/core": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@argos-ci/core/-/core-2.4.1.tgz", - "integrity": "sha512-Sl+5Zq4LBZF+CDB0eXGdTOLv3E9bubO2tfpDncQku5/s/N+2Ptn0JAw/Vc3EdJAtMWj1G8uy+6cvtV+eaVNnFg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@argos-ci/core/-/core-2.5.0.tgz", + "integrity": "sha512-xNHKWzuSLHXm/5fhdEQv8zUwExeEkYzw6CV/Ha9rUBBTPomZL5CNxpXQ/ww1AA4mRC5dq3CfgreRq8qj7HQMVQ==", "dev": true, "license": "MIT", "dependencies": { - "@argos-ci/util": "2.1.0", - "axios": "^1.6.8", + "@argos-ci/api-client": "0.2.0", + "@argos-ci/util": "2.1.1", + "axios": "^1.7.4", "convict": "^6.2.4", - "debug": "^4.3.4", + "debug": "^4.3.6", "fast-glob": "^3.3.2", - "sharp": "^0.33.3", + "sharp": "^0.33.5", "tmp": "^0.2.3" }, "engines": { @@ -833,26 +847,26 @@ } }, "node_modules/@argos-ci/playwright": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@argos-ci/playwright/-/playwright-3.4.1.tgz", - "integrity": "sha512-zJJmztOVmkzrn5iuB0yAVcBvHGKFqfMZ1oq11eWspXk+eyAPcfBSlpoP4ss9xyxKuXbhOB8FWQbKkd8hV7MV4Q==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@argos-ci/playwright/-/playwright-3.5.0.tgz", + "integrity": "sha512-iaIt/LidhZtaZlOHx5VddQsGJJtU6ttF6ABzMgSCY4ckKYxl/oJzkMdZOsIsSouTbqOkDRQBgz+UUMWpN+QaNQ==", "dev": true, "license": "MIT", "dependencies": { - "@argos-ci/browser": "2.1.2", - "@argos-ci/core": "2.4.1", - "@argos-ci/util": "2.1.0", + "@argos-ci/browser": "2.1.3", + "@argos-ci/core": "2.5.0", + "@argos-ci/util": "2.1.1", "chalk": "^5.3.0", - "debug": "^4.3.4" + "debug": "^4.3.6" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@argos-ci/util": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@argos-ci/util/-/util-2.1.0.tgz", - "integrity": "sha512-/78zJjZJCh3i7Eh3/lo7ybXK2pzXFGUNHbK3SgJNKNbFiBDllNRfy+x0kccjvN2gCCDz877jnFOlSoZZuMK56A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@argos-ci/util/-/util-2.1.1.tgz", + "integrity": "sha512-UyACLQe9rvCPbo9muhrLte1AD75kQlcGBuecjmaotaF9MBMj+9Yz+TYs1jJrlLMgqowfIgbXjBYmkXRUn36tCg==", "dev": true, "license": "MIT", "engines": { @@ -20094,6 +20108,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-fetch": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.11.1.tgz", + "integrity": "sha512-WtDQsrvxjXuCmo6u6WMQPfUaya8cLfL+ZCaXorPo9MMumqlU/Km/SrCXsEcJH234D4iykOkvJ6Q/iWBzK7+3rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "openapi-typescript-helpers": "^0.0.12" + } + }, + "node_modules/openapi-typescript-helpers": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.12.tgz", + "integrity": "sha512-FO+5kTWO6KDutigamr2MRwciYkAUYhqdctlyVRrQOe2uxif2/O2+GcS07jNnP36AUK6ubSsGu3GeBiYIc6eQzA==", + "dev": true, + "license": "MIT" + }, "node_modules/openapi3-ts": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-4.3.3.tgz", diff --git a/package.json b/package.json index 21d64eed3..d3272d839 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "packageManager": "npm@10.5.0", "devDependencies": { "@0no-co/graphqlsp": "^1.12.13", - "@argos-ci/playwright": "^3.4.1", + "@argos-ci/playwright": "^3.5.0", "@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/client-preset": "^4.3.3", "@graphql-codegen/fragment-matcher": "^5.0.2", diff --git a/playwright.config.mjs b/playwright.config.mjs index e5a437e0b..01528b600 100644 --- a/playwright.config.mjs +++ b/playwright.config.mjs @@ -1,5 +1,6 @@ // @ts-check -import { devices } from "@playwright/test"; +import { getCSPScriptHash } from "@argos-ci/playwright"; +import { defineConfig, devices } from "@playwright/test"; import argosConfig from "./apps/backend/src/config/index.js"; @@ -13,7 +14,7 @@ import argosConfig from "./apps/backend/src/config/index.js"; * @see https://playwright.dev/docs/test-configuration * @type {import('@playwright/test').PlaywrightTestConfig} */ -const config = { +const config = defineConfig({ testDir: "./tests", /* Maximum time one test can run for. */ timeout: 30 * 1000, @@ -77,7 +78,10 @@ const config = { port: 3000, timeout: 10 * 1000, reuseExistingServer: false, + env: { + CSP_SCRIPT_SRC: `${getCSPScriptHash()},'unsafe-eval'`, + }, }, -}; +}); export default config;