From c0d0c9ada2c7316b724d8b8c3a15a5544a1ada15 Mon Sep 17 00:00:00 2001 From: Ry0taK <49341894+Ry0taK@users.noreply.github.com> Date: Sat, 18 Mar 2023 02:15:36 +0000 Subject: [PATCH] WIP: Send nonce in CSP --- packages/backend/src/@types/fastify.d.ts | 9 +++++++++ .../backend/src/server/web/ClientServerService.ts | 11 ++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 packages/backend/src/@types/fastify.d.ts diff --git a/packages/backend/src/@types/fastify.d.ts b/packages/backend/src/@types/fastify.d.ts new file mode 100644 index 0000000000..83712cc6b6 --- /dev/null +++ b/packages/backend/src/@types/fastify.d.ts @@ -0,0 +1,9 @@ +import FastifyReply from "fastify"; + +declare module 'fastify' { + interface FastifyReply { + cspNonce: { + script: string + } + } +} diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 94679c14ed..e347017960 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -1,5 +1,6 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { randomBytes } from 'node:crypto'; import { Inject, Injectable } from '@nestjs/common'; import { createBullBoard } from '@bull-board/api'; import { BullAdapter } from '@bull-board/api/bullAdapter.js'; @@ -174,12 +175,16 @@ export class ClientServerService { reply.header('X-Frame-Options', 'DENY'); // XSSが存在した場合に影響を軽減する - // (script-srcにunsafe-inline等を追加すると意味が無くなるので注意) + // (インラインスクリプトはreply.cspNonce内の値をnonce属性に設定することで使える) + const scriptNonce = randomBytes(16).toString('hex'); + reply.cspNonce = { + script: scriptNonce, + }; const csp = this.config.contentSecurityPolicy ?? 'script-src \'self\' ' + - 'https://challenges.cloudflare.com https://hcaptcha.com https://*.hcaptcha.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://www.recaptcha.net/recaptcha/; ' + + 'https://challenges.cloudflare.com https://hcaptcha.com https://*.hcaptcha.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://www.recaptcha.net/recaptcha/ {scriptNonce}; ' + 'base-uri \'self\'; object-src \'self\'; report-uri /csp-error'; - reply.header('Content-Security-Policy-Report-Only', csp); + reply.header('Content-Security-Policy-Report-Only', csp.replace('{scriptNonce}', `'nonce-${scriptNonce}'`)); done(); });