From b70308d990cad8ff976c64ab09ec84ff7a5a423d Mon Sep 17 00:00:00 2001 From: Ro Date: Fri, 7 Jan 2022 15:45:35 -0800 Subject: [PATCH] fixed src removal from image tags with relative urls, add iframe tag to allowed list --- brain/data/Contents.inc.php | 34 +- composer.json | 3 +- composer.lock | 44 +- package.json | 3 +- public/assets/scripts/Start.js | 8354 +------------------------------- 5 files changed, 78 insertions(+), 8360 deletions(-) diff --git a/brain/data/Contents.inc.php b/brain/data/Contents.inc.php index 00091f7..010e1d7 100644 --- a/brain/data/Contents.inc.php +++ b/brain/data/Contents.inc.php @@ -7,6 +7,11 @@ use League\CommonMark\Extension\FrontMatter\FrontMatterExtension; use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter; use League\CommonMark\MarkdownConverter; use League\CommonMark\CommonMarkConverter; + +use HtmlSanitizer\Extension\Basic\BasicExtension; +use HtmlSanitizer\Extension\Iframe\IframeExtension; +use HtmlSanitizer\SanitizerBuilder; + use function _\orderBy; class Contents @@ -63,16 +68,35 @@ class Contents ->parse(file_get_contents($file)); //never trust the front end. clean it up - $sanitizer = HtmlSanitizer\Sanitizer::create([ - "extensions" => ["basic", "image", "list", "code"], + + $builder = new SanitizerBuilder(); + $builder->registerExtension(new BasicExtension()); + $builder->registerExtension(new IframeExtension()); + + //relative-a and relative-image + $builder->registerExtension( + new \HtmlSanitizer\Extension\Relative\A\AExtension() + ); + $builder->registerExtension( + new \HtmlSanitizer\Extension\Relative\Image\ImageExtension() + ); + + $detergent = [ + "extensions" => ["basic", "relative-a", "relative-image", "iframe"], "tags" => [ + "div" => [ + "allowed_attributes" => ["class", "title"], + ], "img" => [ "allowed_attributes" => ["src", "alt", "title", "class"], - "allowed_hosts" => null, - "allow_relative_links" => true, + ], + "iframe" => [ + "allowed_attributes" => ["height", "width", "title", "src"], ], ], - ]); + ]; + + $sanitizer = $builder->build($detergent); $scrubbed = $sanitizer->sanitize($result->getContent()); diff --git a/composer.json b/composer.json index 93405de..25e5c5d 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "tgalopin/html-sanitizer": "^1.4", "phpmailer/phpmailer": "^6.4", "league/commonmark": "^2.1", - "symfony/yaml": "^5.4" + "symfony/yaml": "^5.4", + "olegatro/html-sanitizer-relative": "^1.0" } } diff --git a/composer.lock b/composer.lock index 9c87723..4fd885f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aaecaa98ed680188418b8aff96553235", + "content-hash": "cfedfb006726f5c6b4bac05285ccf5e8", "packages": [ { "name": "dflydev/dot-access-data", @@ -858,6 +858,48 @@ }, "time": "2018-02-13T20:26:39+00:00" }, + { + "name": "olegatro/html-sanitizer-relative", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/olegatro/html-sanitizer-relative.git", + "reference": "1a4d4683c0c162653da6dcfe6050476dd8bfc026" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/olegatro/html-sanitizer-relative/zipball/1a4d4683c0c162653da6dcfe6050476dd8bfc026", + "reference": "1a4d4683c0c162653da6dcfe6050476dd8bfc026", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=7.1", + "tgalopin/html-sanitizer": "^1.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "HtmlSanitizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oleg Scherbakov", + "email": "shcherbakov.oleg88@gmail.com" + } + ], + "description": "Extension for html-sanitizer library by allowing relative urls in the A and Image tags", + "support": { + "issues": "https://github.com/olegatro/html-sanitizer-relative/issues", + "source": "https://github.com/olegatro/html-sanitizer-relative/tree/1.0.0" + }, + "time": "2021-02-05T13:39:44+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v6.5.1", diff --git a/package.json b/package.json index 9043e51..309a3f8 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "license": "UNLICENSED", "author": "Are0h", "scripts": { - "watch": "sass --watch src/styles:public/assets/css & npx parcel watch src/com/Start.js --dist-dir public/assets/scripts --public-url /assets/scripts" + "watch": "sass --watch src/styles:public/assets/css & npx parcel watch src/com/Start.js --dist-dir public/assets/scripts --public-url /assets/scripts", + "build": "sass src/styles:public/assets/css & npx parcel build src/com/Start.js --dist-dir public/assets/scripts --public-url /assets/scripts" }, "description": "Front end script for the most chill blog framework ever.", "repository": "https://code.playvicio.us/Are0h/Fipamo" diff --git a/public/assets/scripts/Start.js b/public/assets/scripts/Start.js index a50391d..17847c2 100644 --- a/public/assets/scripts/Start.js +++ b/public/assets/scripts/Start.js @@ -1,8358 +1,8 @@ -// modules are defined as an array -// [ module function, map of requires ] -// -// map of requires is short require name -> numeric require -// -// anything defined in a previous bundle is accessed via the -// orig method which is the require for previous bundles - -(function (modules, entry, mainEntry, parcelRequireName, globalName) { - /* eslint-disable no-undef */ - var globalObject = - typeof globalThis !== 'undefined' - ? globalThis - : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' - ? window - : typeof global !== 'undefined' - ? global - : {}; - /* eslint-enable no-undef */ - - // Save the require from previous bundle to this closure if any - var previousRequire = - typeof globalObject[parcelRequireName] === 'function' && - globalObject[parcelRequireName]; - - var cache = previousRequire.cache || {}; - // Do not use `require` to prevent Webpack from trying to bundle this call - var nodeRequire = - typeof module !== 'undefined' && - typeof module.require === 'function' && - module.require.bind(module); - - function newRequire(name, jumped) { - if (!cache[name]) { - if (!modules[name]) { - // if we cannot find the module within our internal map or - // cache jump to the current global require ie. the last bundle - // that was added to the page. - var currentRequire = - typeof globalObject[parcelRequireName] === 'function' && - globalObject[parcelRequireName]; - if (!jumped && currentRequire) { - return currentRequire(name, true); - } - - // If there are other bundles on this page the require from the - // previous one is saved to 'previousRequire'. Repeat this as - // many times as there are bundles until the module is found or - // we exhaust the require chain. - if (previousRequire) { - return previousRequire(name, true); - } - - // Try the node require function if it exists. - if (nodeRequire && typeof name === 'string') { - return nodeRequire(name); - } - - var err = new Error("Cannot find module '" + name + "'"); - err.code = 'MODULE_NOT_FOUND'; - throw err; - } - - localRequire.resolve = resolve; - localRequire.cache = {}; - - var module = (cache[name] = new newRequire.Module(name)); - - modules[name][0].call( - module.exports, - localRequire, - module, - module.exports, - this - ); - } - - return cache[name].exports; - - function localRequire(x) { - return newRequire(localRequire.resolve(x)); - } - - function resolve(x) { - return modules[name][1][x] || x; - } - } - - function Module(moduleName) { - this.id = moduleName; - this.bundle = newRequire; - this.exports = {}; - } - - newRequire.isParcelRequire = true; - newRequire.Module = Module; - newRequire.modules = modules; - newRequire.cache = cache; - newRequire.parent = previousRequire; - newRequire.register = function (id, exports) { - modules[id] = [ - function (require, module) { - module.exports = exports; - }, - {}, - ]; - }; - - Object.defineProperty(newRequire, 'root', { - get: function () { - return globalObject[parcelRequireName]; - }, - }); - - globalObject[parcelRequireName] = newRequire; - - for (var i = 0; i < entry.length; i++) { - newRequire(entry[i]); - } - - if (mainEntry) { - // Expose entry point to Node, AMD or browser globals - // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js - var mainExports = newRequire(mainEntry); - - // CommonJS - if (typeof exports === 'object' && typeof module !== 'undefined') { - module.exports = mainExports; - - // RequireJS - } else if (typeof define === 'function' && define.amd) { - define(function () { - return mainExports; - }); - - //