From c73fbc9217b219e18a2fceab7a610186e316fb31 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Tue, 8 Apr 2025 00:03:48 +0200 Subject: [PATCH] refactor: use iframes for gist embedding instead of gist-embed The used library gist-embed relies on GitHub Gist's JSONP endpoint which is a risk for XSS injection. By adding untrusted content from GitHub into the DOM it also follows very bad practises. Using the iframe embedding has the disadvantage of not having the proper height for the frame auto-loaded, but the security benefits are worth it. Signed-off-by: Erik Michelson --- lib/csp.js | 5 ++--- package.json | 1 - public/css/extra.css | 5 +++++ public/js/extra.js | 11 +---------- public/js/htmlExport.js | 1 - yarn.lock | 8 -------- 6 files changed, 8 insertions(+), 23 deletions(-) diff --git a/lib/csp.js b/lib/csp.js index ac06722d6..e6827758d 100644 --- a/lib/csp.js +++ b/lib/csp.js @@ -10,18 +10,17 @@ const defaultDirectives = { connectSrc: ['\'self\'', buildDomainOriginWithProtocol(config, 'ws')], fontSrc: ['\'self\''], manifestSrc: ['\'self\''], - frameSrc: ['\'self\'', 'https://player.vimeo.com', 'https://www.slideshare.net/slideshow/embed_code/key/', 'https://www.youtube.com'], + frameSrc: ['\'self\'', 'https://player.vimeo.com', 'https://www.slideshare.net/slideshow/embed_code/key/', 'https://www.youtube.com', 'https://gist.github.com'], imgSrc: ['*', 'data:'], // we allow using arbitrary images & explicit data for mermaid scriptSrc: [ config.serverURL + '/build/', config.serverURL + '/js/', config.serverURL + '/config', - 'https://gist.github.com/', 'https://vimeo.com/api/oembed.json', 'https://www.slideshare.net/api/oembed/2', '\'unsafe-inline\'' // this is ignored by browsers supporting nonces/hashes ], - styleSrc: [config.serverURL + '/build/', config.serverURL + '/css/', '\'unsafe-inline\'', 'https://github.githubassets.com'], // unsafe-inline is required for some libs, plus used in views + styleSrc: [config.serverURL + '/build/', config.serverURL + '/css/', '\'unsafe-inline\''], // unsafe-inline is required for some libs, plus used in views objectSrc: ['*'], // Chrome PDF viewer treats PDFs as objects :/ formAction: ['\'self\''], mediaSrc: ['*'] diff --git a/package.json b/package.json index e1196330f..35c4756f9 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,6 @@ "file-saver": "2.0.5", "flowchart.js": "1.18.0", "fork-awesome": "1.2.0", - "gist-embed": "2.6.0", "globals": "16.0.0", "highlight.js": "10.7.3", "html-webpack-plugin": "4.5.2", diff --git a/public/css/extra.css b/public/css/extra.css index d5945ba93..d108a5ec1 100644 --- a/public/css/extra.css +++ b/public/css/extra.css @@ -63,6 +63,11 @@ -webkit-transition: opacity 0.2s; /* Safari */ transition: opacity 0.2s; } +iframe.github-gist-frame { + width: 100%; + border: none; + height: 32rem; +} .slideshare .inner, .speakerdeck .inner { diff --git a/public/js/extra.js b/public/js/extra.js index 210f8da9d..36668b1c3 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -15,8 +15,6 @@ import markdownitContainer from 'markdown-it-container' /* Defined regex markdown it plugins */ import Plugin from 'markdown-it-regexp' -import 'gist-embed' - require('prismjs/themes/prism.css') require('prismjs/components/prism-wiki') require('prismjs/components/prism-haskell') @@ -304,10 +302,6 @@ export function finishView (view) { } }) }) - // gist - view.find('code[data-gist-id]').each((key, value) => { - if ($(value).children().length === 0) { $(value).gist(window.viewAjaxCallback) } - }) // sequence diagram const sequences = view.find('div.sequence-diagram.raw').removeClass('raw') sequences.each((key, value) => { @@ -639,8 +633,6 @@ function generateCleanHTML (view) { src.find('*[class=""]').removeAttr('class') eles.removeAttr('data-startline data-endline') src.find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll') - // remove gist content - src.find('code[data-gist-id]').children().remove() // disable todo list src.find('input.task-list-item-checkbox').attr('disabled', '') // replace emoji image path @@ -1156,8 +1148,7 @@ const gistPlugin = new Plugin( (match, utils) => { const gistid = match[1] - const code = `` - return code + return `` } ) // TOC diff --git a/public/js/htmlExport.js b/public/js/htmlExport.js index 676e2b1bc..2f4a09872 100644 --- a/public/js/htmlExport.js +++ b/public/js/htmlExport.js @@ -22,4 +22,3 @@ const $ = require('jquery') window.jQuery = $ window.$ = $ require('bootstrap') -require('gist-embed/gist-embed.min') diff --git a/yarn.lock b/yarn.lock index 5c47a60d1..3fbdf2d80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1395,7 +1395,6 @@ __metadata: flowchart.js: "npm:1.18.0" fork-awesome: "npm:1.2.0" formidable: "npm:2.1.2" - gist-embed: "npm:2.6.0" globals: "npm:16.0.0" graceful-fs: "npm:4.2.11" helmet: "npm:8.1.0" @@ -7421,13 +7420,6 @@ __metadata: languageName: node linkType: hard -"gist-embed@npm:2.6.0": - version: 2.6.0 - resolution: "gist-embed@npm:2.6.0" - checksum: 10/6b9e1266e86f856a0ba64f27fe735748f1754b8a945b629ff5ab7705554a274d06ead0c177f503d4d94490851abb4caf533ef076c9d794ecc34c142491b4aff6 - languageName: node - linkType: hard - "github-from-package@npm:0.0.0": version: 0.0.0 resolution: "github-from-package@npm:0.0.0"