diff --git a/app/Entities/Tools/PageContent.php b/app/Entities/Tools/PageContent.php
index 82499cdf2..ff502d164 100644
--- a/app/Entities/Tools/PageContent.php
+++ b/app/Entities/Tools/PageContent.php
@@ -4,6 +4,7 @@ use BookStack\Entities\Models\Page;
 use BookStack\Entities\Tools\Markdown\CustomStrikeThroughExtension;
 use BookStack\Facades\Theme;
 use BookStack\Theming\ThemeEvents;
+use BookStack\Util\HtmlContentFilter;
 use DOMDocument;
 use DOMNodeList;
 use DOMXPath;
@@ -169,7 +170,7 @@ class PageContent
         $content = $this->page->html;
 
         if (!config('app.allow_content_scripts')) {
-            $content = $this->escapeScripts($content);
+            $content = HtmlContentFilter::removeScripts($content);
         }
 
         if ($blankIncludes) {
@@ -308,65 +309,4 @@ class PageContent
 
         return $innerContent;
     }
-
-    /**
-     * Escape script tags within HTML content.
-     */
-    protected function escapeScripts(string $html) : string
-    {
-        if (empty($html)) {
-            return $html;
-        }
-
-        libxml_use_internal_errors(true);
-        $doc = new DOMDocument();
-        $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
-        $xPath = new DOMXPath($doc);
-
-        // Remove standard script tags
-        $scriptElems = $xPath->query('//script');
-        foreach ($scriptElems as $scriptElem) {
-            $scriptElem->parentNode->removeChild($scriptElem);
-        }
-
-        // Remove clickable links to JavaScript URI
-        $badLinks = $xPath->query('//*[contains(@href, \'javascript:\')]');
-        foreach ($badLinks as $badLink) {
-            $badLink->parentNode->removeChild($badLink);
-        }
-
-        // Remove forms with calls to JavaScript URI
-        $badForms = $xPath->query('//*[contains(@action, \'javascript:\')] | //*[contains(@formaction, \'javascript:\')]');
-        foreach ($badForms as $badForm) {
-            $badForm->parentNode->removeChild($badForm);
-        }
-
-        // Remove meta tag to prevent external redirects
-        $metaTags = $xPath->query('//meta[contains(@content, \'url\')]');
-        foreach ($metaTags as $metaTag) {
-            $metaTag->parentNode->removeChild($metaTag);
-        }
-
-        // Remove data or JavaScript iFrames
-        $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]');
-        foreach ($badIframes as $badIframe) {
-            $badIframe->parentNode->removeChild($badIframe);
-        }
-
-        // Remove 'on*' attributes
-        $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
-        foreach ($onAttributes as $attr) {
-            /** @var \DOMAttr $attr*/
-            $attrName = $attr->nodeName;
-            $attr->parentNode->removeAttribute($attrName);
-        }
-
-        $html = '';
-        $topElems = $doc->documentElement->childNodes->item(0)->childNodes;
-        foreach ($topElems as $child) {
-            $html .= $doc->saveHTML($child);
-        }
-
-        return $html;
-    }
 }
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
index 31736e1b0..1ffb99f8d 100644
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -105,7 +105,7 @@ class HomeController extends Controller
      */
     public function customHeadContent()
     {
-        return view('partials.custom-head-content');
+        return view('partials.custom-head');
     }
 
     /**
diff --git a/app/Util/HtmlContentFilter.php b/app/Util/HtmlContentFilter.php
new file mode 100644
index 000000000..cec927a3c
--- /dev/null
+++ b/app/Util/HtmlContentFilter.php
@@ -0,0 +1,71 @@
+<?php namespace BookStack\Util;
+
+use DOMDocument;
+use DOMNode;
+use DOMNodeList;
+use DOMXPath;
+
+class HtmlContentFilter
+{
+    /**
+     * Remove all of the script elements from the given HTML.
+     */
+    public static function removeScripts(string $html): string
+    {
+        if (empty($html)) {
+            return $html;
+        }
+
+        libxml_use_internal_errors(true);
+        $doc = new DOMDocument();
+        $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
+        $xPath = new DOMXPath($doc);
+
+        // Remove standard script tags
+        $scriptElems = $xPath->query('//script');
+        static::removeNodes($scriptElems);
+
+        // Remove clickable links to JavaScript URI
+        $badLinks = $xPath->query('//*[contains(@href, \'javascript:\')]');
+        static::removeNodes($badLinks);
+
+        // Remove forms with calls to JavaScript URI
+        $badForms = $xPath->query('//*[contains(@action, \'javascript:\')] | //*[contains(@formaction, \'javascript:\')]');
+        static::removeNodes($badForms);
+
+        // Remove meta tag to prevent external redirects
+        $metaTags = $xPath->query('//meta[contains(@content, \'url\')]');
+        static::removeNodes($metaTags);
+
+        // Remove data or JavaScript iFrames
+        $badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]');
+        static::removeNodes($badIframes);
+
+        // Remove 'on*' attributes
+        $onAttributes = $xPath->query('//@*[starts-with(name(), \'on\')]');
+        foreach ($onAttributes as $attr) {
+            /** @var \DOMAttr $attr*/
+            $attrName = $attr->nodeName;
+            $attr->parentNode->removeAttribute($attrName);
+        }
+
+        $html = '';
+        $topElems = $doc->documentElement->childNodes->item(0)->childNodes;
+        foreach ($topElems as $child) {
+            $html .= $doc->saveHTML($child);
+        }
+
+        return $html;
+    }
+
+    /**
+     * Removed all of the given DOMNodes.
+     */
+    static protected function removeNodes(DOMNodeList $nodes): void
+    {
+        foreach ($nodes as $node) {
+            $node->parentNode->removeChild($node);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/resources/views/books/export.blade.php b/resources/views/books/export.blade.php
index f62b89582..1faa3880e 100644
--- a/resources/views/books/export.blade.php
+++ b/resources/views/books/export.blade.php
@@ -27,7 +27,7 @@
         }
     </style>
     @yield('head')
-    @include('partials.custom-head')
+    @include('partials.export-custom-head')
 </head>
 <body>
 
diff --git a/resources/views/chapters/export.blade.php b/resources/views/chapters/export.blade.php
index 506e8db3d..96d9d7700 100644
--- a/resources/views/chapters/export.blade.php
+++ b/resources/views/chapters/export.blade.php
@@ -19,7 +19,7 @@
             }
         }
     </style>
-    @include('partials.custom-head')
+    @include('partials.export-custom-head')
 </head>
 <body>
 
diff --git a/resources/views/pages/export.blade.php b/resources/views/pages/export.blade.php
index 47a4d870a..1f2e60576 100644
--- a/resources/views/pages/export.blade.php
+++ b/resources/views/pages/export.blade.php
@@ -29,7 +29,7 @@
         </style>
     @endif
 
-    @include('partials.custom-head')
+    @include('partials.export-custom-head')
 </head>
 <body>
 
diff --git a/resources/views/partials/custom-head-content.blade.php b/resources/views/partials/custom-head-content.blade.php
deleted file mode 100644
index b245b7ad6..000000000
--- a/resources/views/partials/custom-head-content.blade.php
+++ /dev/null
@@ -1,5 +0,0 @@
-@if(setting('app-custom-head', false))
-    <!-- Custom user content -->
-    {!! setting('app-custom-head') !!}
-    <!-- End custom user content -->
-@endif
\ No newline at end of file
diff --git a/resources/views/partials/custom-head.blade.php b/resources/views/partials/custom-head.blade.php
index dd7cc41e4..fa5ba0cc4 100644
--- a/resources/views/partials/custom-head.blade.php
+++ b/resources/views/partials/custom-head.blade.php
@@ -1,5 +1,5 @@
 @if(setting('app-custom-head') && \Route::currentRouteName() !== 'settings')
-    <!-- Custom user content -->
-    {!! setting('app-custom-head') !!}
-    <!-- End custom user content -->
+<!-- Custom user content -->
+{!! setting('app-custom-head') !!}
+<!-- End custom user content -->
 @endif
\ No newline at end of file
diff --git a/resources/views/partials/export-custom-head.blade.php b/resources/views/partials/export-custom-head.blade.php
new file mode 100644
index 000000000..f428e9fe9
--- /dev/null
+++ b/resources/views/partials/export-custom-head.blade.php
@@ -0,0 +1,5 @@
+@if(setting('app-custom-head'))
+<!-- Custom user content -->
+{!! \BookStack\Util\HtmlContentFilter::removeScripts(setting('app-custom-head')) !!}
+<!-- End custom user content -->
+@endif
\ No newline at end of file
diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php
index 05672c6ca..d04ccc69a 100644
--- a/tests/Entity/ExportTest.php
+++ b/tests/Entity/ExportTest.php
@@ -1,5 +1,6 @@
 <?php namespace Tests\Entity;
 
+use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Page;
 use Illuminate\Support\Facades\Storage;
@@ -214,4 +215,19 @@ class ExportTest extends TestCase
         $resp->assertSee('src="/uploads/svg_test.svg"');
     }
 
+    public function test_exports_removes_scripts_from_custom_head()
+    {
+        $entities = [
+            Page::query()->first(), Chapter::query()->first(), Book::query()->first(),
+        ];
+        setting()->put('app-custom-head', '<script>window.donkey = "cat";</script><style>.my-test-class { color: red; }</style>');
+
+        foreach ($entities as $entity) {
+            $resp = $this->asEditor()->get($entity->getUrl('/export/html'));
+            $resp->assertDontSee('window.donkey');
+            $resp->assertDontSee('script');
+            $resp->assertSee('.my-test-class { color: red; }');
+        }
+    }
+
 }