From f5ba406f36809de7511c7f906ee5fd9f6e508244 Mon Sep 17 00:00:00 2001 From: David Cui <53581635+davidcui1225@users.noreply.github.com> Date: Wed, 15 Jun 2022 13:31:09 -0700 Subject: [PATCH] Markdown patch fix (#1) Signed-off-by: David Cui --- dashboards-reports/package.json | 4 +-- .../report_definition_details.tsx | 4 +-- .../main/report_details/report_details.tsx | 4 +-- .../create/create_report_definition.tsx | 11 -------- .../report_settings/report_settings.tsx | 4 +-- .../server/routes/utils/constants.ts | 28 +++++++++++++++++++ .../utils/visual_report/visualReportHelper.ts | 22 +++++++++++---- dashboards-reports/yarn.lock | 16 +++++------ 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/dashboards-reports/package.json b/dashboards-reports/package.json index 121d07e9..e1195edc 100644 --- a/dashboards-reports/package.json +++ b/dashboards-reports/package.json @@ -19,7 +19,7 @@ "async-mutex": "^0.2.6", "babel-polyfill": "^6.26.0", "cron-validator": "^1.1.1", - "dompurify": "^2.1.1", + "dompurify": "^2.3.8", "elastic-builder": "^2.7.1", "enzyme-adapter-react-16": "^1.15.2", "jest-fetch-mock": "^3.0.3", @@ -41,7 +41,7 @@ }, "devDependencies": { "@elastic/eslint-import-resolver-kibana": "link:../../packages/osd-eslint-import-resolver-opensearch-dashboards", - "@types/dompurify": "^2.0.4", + "@types/dompurify": "^2.3.3", "@types/enzyme-adapter-react-16": "^1.0.6", "@types/jsdom": "^16.2.3", "@types/puppeteer-core": "^2.0.0", diff --git a/dashboards-reports/public/components/main/report_definition_details/report_definition_details.tsx b/dashboards-reports/public/components/main/report_definition_details/report_definition_details.tsx index da42ce0b..7ee263b1 100644 --- a/dashboards-reports/public/components/main/report_definition_details/report_definition_details.tsx +++ b/dashboards-reports/public/components/main/report_definition_details/report_definition_details.tsx @@ -426,12 +426,12 @@ export function ReportDefinitionDetails(props: { match?: any; setBreadcrumbs?: a reportHeader: reportParams.core_params.hasOwnProperty('header') && reportParams.core_params.header != '' - ? converter.makeMarkdown(reportParams.core_params.header) + ? reportParams.core_params.header : `\u2014`, reportFooter: reportParams.core_params.hasOwnProperty('footer') && reportParams.core_params.footer != '' - ? converter.makeMarkdown(reportParams.core_params.footer) + ? reportParams.core_params.footer : `\u2014`, triggerType: triggerType, scheduleDetails: triggerParams diff --git a/dashboards-reports/public/components/main/report_details/report_details.tsx b/dashboards-reports/public/components/main/report_details/report_details.tsx index 9462d9cc..df931aea 100644 --- a/dashboards-reports/public/components/main/report_details/report_details.tsx +++ b/dashboards-reports/public/components/main/report_details/report_details.tsx @@ -229,12 +229,12 @@ export function ReportDetails(props: { match?: any; setBreadcrumbs?: any; httpCl reportHeader: reportParams.core_params.hasOwnProperty('header') && reportParams.core_params.header != '' - ? converter.makeMarkdown(reportParams.core_params.header) + ? reportParams.core_params.header : `\u2014`, reportFooter: reportParams.core_params.hasOwnProperty('footer') && reportParams.core_params.footer != '' - ? converter.makeMarkdown(reportParams.core_params.footer) + ? reportParams.core_params.footer : `\u2014`, triggerType: triggerType, scheduleType: triggerParams ? triggerParams.schedule_type : `\u2014`, diff --git a/dashboards-reports/public/components/report_definitions/create/create_report_definition.tsx b/dashboards-reports/public/components/report_definitions/create/create_report_definition.tsx index 51ba193a..eed7015a 100644 --- a/dashboards-reports/public/components/report_definitions/create/create_report_definition.tsx +++ b/dashboards-reports/public/components/report_definitions/create/create_report_definition.tsx @@ -250,17 +250,6 @@ export function CreateReport(props: { [x: string]: any; setBreadcrumbs?: any; ht setPreErrorData(metadata); setComingFromError(true); } else { - // convert header and footer to html - if ('header' in metadata.report_params.core_params) { - metadata.report_params.core_params.header = converter.makeHtml( - metadata.report_params.core_params.header - ); - } - if ('footer' in metadata.report_params.core_params) { - metadata.report_params.core_params.footer = converter.makeHtml( - metadata.report_params.core_params.footer - ); - } httpClient .post('../api/reporting/reportDefinition', { body: JSON.stringify(metadata), diff --git a/dashboards-reports/public/components/report_definitions/report_settings/report_settings.tsx b/dashboards-reports/public/components/report_definitions/report_settings/report_settings.tsx index 10cfe40b..0db86cfd 100644 --- a/dashboards-reports/public/components/report_definitions/report_settings/report_settings.tsx +++ b/dashboards-reports/public/components/report_definitions/report_settings/report_settings.tsx @@ -374,13 +374,13 @@ export function ReportSettings(props: ReportSettingProps) { if (header) { checkboxIdSelectHeaderFooter.header = true; if (!unmounted) { - setHeader(converter.makeMarkdown(header)); + setHeader(header); } } if (footer) { checkboxIdSelectHeaderFooter.footer = true; if (!unmounted) { - setFooter(converter.makeMarkdown(footer)); + setFooter(footer); } } }) diff --git a/dashboards-reports/server/routes/utils/constants.ts b/dashboards-reports/server/routes/utils/constants.ts index 1e0d1322..dffb0cd1 100644 --- a/dashboards-reports/server/routes/utils/constants.ts +++ b/dashboards-reports/server/routes/utils/constants.ts @@ -4,6 +4,7 @@ */ import { CountersType } from './types'; +import Showdown from 'showdown'; export enum FORMAT { pdf = 'pdf', @@ -78,7 +79,34 @@ export const EXTRA_HEADERS = [ 'x-forwarded-for', ]; +export const converter = new Showdown.Converter({ + tables: true, + simplifiedAutoLink: true, + strikethrough: true, + tasklists: true, + noHeaderId: true, +}); + +const BLOCKED_KEYWORD = 'BLOCKED_KEYWORD'; +const ipv4Regex = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])/g +const ipv6Regex = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/g; +const localhostRegex = /localhost:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])/g; +const iframeRegex = /iframe/g; + +export const replaceBlockedKeywords = (htmlString: string) => { + // replace : + htmlString = htmlString.replace(ipv4Regex, BLOCKED_KEYWORD); + // replace ipv6 addresses + htmlString = htmlString.replace(ipv6Regex, BLOCKED_KEYWORD); + // replace iframe keyword + htmlString = htmlString.replace(iframeRegex, BLOCKED_KEYWORD); + // replace localhost: + htmlString = htmlString.replace(localhostRegex, BLOCKED_KEYWORD); + return htmlString; +} + export const CHROMIUM_PATH = `${__dirname}/../../../.chromium/headless_shell`; + /** * Metric constants diff --git a/dashboards-reports/server/routes/utils/visual_report/visualReportHelper.ts b/dashboards-reports/server/routes/utils/visual_report/visualReportHelper.ts index 51d19f92..d98d1824 100644 --- a/dashboards-reports/server/routes/utils/visual_report/visualReportHelper.ts +++ b/dashboards-reports/server/routes/utils/visual_report/visualReportHelper.ts @@ -18,6 +18,7 @@ import { import { getFileName } from '../helpers'; import { CreateReportResultType } from '../types'; import { ReportParamsSchemaType, VisualReportSchemaType } from 'server/model'; +import { converter, replaceBlockedKeywords } from '../constants'; import fs from 'fs'; import _ from 'lodash'; @@ -45,10 +46,21 @@ export const createVisualReport = async ( const window = new JSDOM('').window; const DOMPurify = createDOMPurify(window); - const reportHeader = header - ? DOMPurify.sanitize(header) + let keywordFilteredHeader = header + ? converter.makeHtml(header) : DEFAULT_REPORT_HEADER; - const reportFooter = footer ? DOMPurify.sanitize(footer) : ''; + let keywordFilteredFooter = footer ? converter.makeHtml(footer) : ''; + + keywordFilteredHeader = DOMPurify.sanitize(keywordFilteredHeader); + keywordFilteredFooter = DOMPurify.sanitize(keywordFilteredFooter); + + // filter blocked keywords in header and footer + if (keywordFilteredHeader !== '') { + keywordFilteredHeader = replaceBlockedKeywords(keywordFilteredHeader); + } + if (keywordFilteredFooter !== '') { + keywordFilteredFooter = replaceBlockedKeywords(keywordFilteredFooter); + } // set up puppeteer const browser = await puppeteer.launch({ @@ -151,8 +163,8 @@ export const createVisualReport = async ( await waitForDynamicContent(page); await addReportStyle(page); - await addReportHeader(page, reportHeader); - await addReportFooter(page, reportFooter); + await addReportHeader(page, keywordFilteredHeader); + await addReportFooter(page, keywordFilteredFooter); // create pdf or png accordingly if (reportFormat === FORMAT.pdf) { diff --git a/dashboards-reports/yarn.lock b/dashboards-reports/yarn.lock index 682fa09b..63e4de21 100644 --- a/dashboards-reports/yarn.lock +++ b/dashboards-reports/yarn.lock @@ -568,10 +568,10 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== -"@types/dompurify@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.0.4.tgz#25fce15f1f4b1bc0df0ad957040cf226416ac2d7" - integrity sha512-y6K7NyXTQvjr8hJNsAFAD8yshCsIJ0d+OYEFzULuIqWyWOKL2hRru1I+rorI5U0K4SLAROTNuSUFXPDTu278YA== +"@types/dompurify@^2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.3.3.tgz#c24c92f698f77ed9cc9d9fa7888f90cf2bfaa23f" + integrity sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w== dependencies: "@types/trusted-types" "*" @@ -2207,10 +2207,10 @@ domhandler@^3.0, domhandler@^3.0.0: dependencies: domelementtype "^2.0.1" -dompurify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.1.1.tgz#b5aa988676b093a9c836d8b855680a8598af25fe" - integrity sha512-NijiNVkS/OL8mdQL1hUbCD6uty/cgFpmNiuFxrmJ5YPH2cXrPKIewoixoji56rbZ6XBPmtM8GA8/sf9unlSuwg== +dompurify@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f" + integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw== domutils@^2.0.0: version "2.2.0"