From 8cfb47b6376e82251445856f9a3fd54c40c9fe77 Mon Sep 17 00:00:00 2001 From: Gleb Voitenko Date: Mon, 11 Nov 2024 15:28:30 +0300 Subject: [PATCH] feat: change custom csp in md2md mode --- package-lock.json | 9 ++++ package.json | 1 + src/constants.ts | 12 +++++ src/models.ts | 4 +- src/pages/document.ts | 45 ++++++++++++++++++- src/steps/processAssets.ts | 10 +++-- .../load-custom-resources.spec.ts.snap | 24 +++++----- tests/e2e/__snapshots__/metadata.spec.ts.snap | 12 ++--- tests/e2e/__snapshots__/rtl.spec.ts.snap | 24 +++++----- 9 files changed, 105 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index a77975a8..cd1b4b93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@diplodoc/client": "^3.1.6", "@diplodoc/translation": "^1.4.3", + "csp-header": "^5.2.1", "katex": "^0.16.9", "shelljs": "0.8.5", "threads": "1.7.0", @@ -5710,6 +5711,14 @@ "node": ">= 8" } }, + "node_modules/csp-header": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/csp-header/-/csp-header-5.2.1.tgz", + "integrity": "sha512-qOJNu39JZkPrbrAM40a1tQCePEPYVIoI6nMDhX4RA07QjU8efS+zyd/zE83XJu85KKazH9NjKlvvlswFMteMgg==", + "engines": { + "node": ">=10" + } + }, "node_modules/css": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", diff --git a/package.json b/package.json index 676ff130..4e61f7f7 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "dependencies": { "@diplodoc/client": "^3.1.6", "@diplodoc/translation": "^1.4.3", + "csp-header": "^5.2.1", "katex": "^0.16.9", "shelljs": "0.8.5", "threads": "1.7.0", diff --git a/src/constants.ts b/src/constants.ts index ee681083..9091ac78 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -40,6 +40,18 @@ export const SINGLE_PAGE_DATA_FILENAME = 'single-page.json'; export const CUSTOM_STYLE = 'custom-style'; export const SEARCH_API = join(ASSETS_FOLDER, 'search', 'index.js'); export const SEARCH_LANGS = join(ASSETS_FOLDER, 'search', 'langs'); +export const DEFAULT_CSP_SETTINGS: Record = { + 'default-src': ["'self'"], + 'script-src': ["'self'", "'unsafe-inline'"], + 'style-src': ["'self'", "'unsafe-inline'"], + 'img-src': ["'self'", 'data:'], + 'font-src': ["'self'", 'data:'], + 'connect-src': ["'self'"], + 'frame-src': ["'none'"], + 'object-src': ["'none'"], + 'base-uri': ["'self'"], + 'form-action': ["'self'"], +}; export enum Stage { NEW = 'new', diff --git a/src/models.ts b/src/models.ts index fac12d6b..a7bef3fb 100644 --- a/src/models.ts +++ b/src/models.ts @@ -294,7 +294,9 @@ export interface PathData { } export type Resources = { - [key in ResourceType]?: string[]; + [key in Exclude]?: string[]; +} & { + csp?: Record[]; }; export type YandexCloudTranslateGlossaryPair = { diff --git a/src/pages/document.ts b/src/pages/document.ts index 2a359239..3dcd39f5 100644 --- a/src/pages/document.ts +++ b/src/pages/document.ts @@ -1,6 +1,12 @@ import {join} from 'path'; -import {BUNDLE_FOLDER, CARRIAGE_RETURN, CUSTOM_STYLE, RTL_LANGS} from '../constants'; +import { + BUNDLE_FOLDER, + CARRIAGE_RETURN, + CUSTOM_STYLE, + DEFAULT_CSP_SETTINGS, + RTL_LANGS, +} from '../constants'; import {LeadingPage, Resources, TextItems, VarsMetadata} from '../models'; import {ArgvService, PluginService} from '../services'; import {getDepthPath} from '../utils'; @@ -9,6 +15,7 @@ import {DocInnerProps, DocPageData, render} from '@diplodoc/client/ssr'; import manifest from '@diplodoc/client/manifest'; import {escape} from 'html-escaper'; +import {getCSP} from 'csp-header'; export interface TitleMeta { title?: string; @@ -24,7 +31,8 @@ export function generateStaticMarkup( tocPath: string, title: string, ): string { - const {style, script, metadata, ...restYamlConfigMeta} = (props.data.meta as Meta) || {}; + /* @todo replace rest operator with proper unpacking */ + const {style, script, csp, metadata, ...restYamlConfigMeta} = (props.data.meta as Meta) || {}; const resources = getResources({style, script}); const {staticContent} = ArgvService.getConfig(); @@ -41,6 +49,7 @@ export function generateStaticMarkup( ${getMetadata(metadata, restYamlConfigMeta)} + ${generateCSP(csp)} ${title}