]> BookStack Code Mirror - bookstack/commitdiff
Added untrusted server fetching control
authorDan Brown <redacted>
Tue, 31 Aug 2021 19:22:42 +0000 (20:22 +0100)
committerDan Brown <redacted>
Tue, 31 Aug 2021 19:22:42 +0000 (20:22 +0100)
WKHTMLtoPDF provides limited control for external fetching
so that will now be disabled by default unless
ALLOW_UNTRUSTED_SERVER_FETCHING=true is specifically set.
This new option will also control DOMPDF fetching.

.env.example.complete
app/Config/app.php
app/Config/dompdf.php
app/Entities/Tools/ExportFormatter.php
phpunit.xml
tests/Entity/ExportTest.php
tests/Unit/ConfigTest.php

index 26df8f3cb8e918102ddc73fe8fae0a812bc1d33e..49d834ff76df2e82f64433be25d31311a7c2111f 100644 (file)
@@ -281,6 +281,12 @@ ALLOW_CONTENT_SCRIPTS=false
 # Contents of the robots.txt file can be overridden, making this option obsolete.
 ALLOW_ROBOTS=null
 
+# Allow server-side fetches to be performed to potentially unknown
+# and user-provided locations. Primarily used in exports when loading
+# in externally referenced assets.
+# Can be 'true' or 'false'.
+ALLOW_UNTRUSTED_SERVER_FETCHING=false
+
 # A list of hosts that BookStack can be iframed within.
 # Space separated if multiple. BookStack host domain is auto-inferred.
 # For Example: ALLOWED_IFRAME_HOSTS="https://example.com https://a.example.com"
index a09c329ce738e2d72c0741faed88759a89520ef7..6f1901065a9e179bcedebf55237bc3945bd81907 100755 (executable)
@@ -36,6 +36,11 @@ return [
     // Even when overridden the WYSIWYG editor may still escape script content.
     'allow_content_scripts' => env('ALLOW_CONTENT_SCRIPTS', false),
 
+    # Allow server-side fetches to be performed to potentially unknown
+    # and user-provided locations. Primarily used in exports when loading
+    # in externally referenced assets.
+    'allow_untrusted_server_fetching' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
+
     // Override the default behaviour for allowing crawlers to crawl the instance.
     // May be ignored if view has be overridden or modified.
     // Defaults to null since, if not set, 'app-public' status used instead.
index 71ea716f38729b6073ae96c48eb07c1bafd2a755..cf07312e8a25854b4387376fbe015789a4773602 100644 (file)
@@ -37,7 +37,7 @@ return [
          * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
          * Symbol, ZapfDingbats.
          */
-        'DOMPDF_FONT_DIR' => storage_path('fonts/'),  // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
+        'font_dir' => storage_path('fonts/'),  // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
 
         /**
          * The location of the DOMPDF font cache directory.
@@ -47,7 +47,7 @@ return [
          *
          * Note: This directory must exist and be writable by the webserver process.
          */
-        'DOMPDF_FONT_CACHE' => storage_path('fonts/'),
+        'font_cache' => storage_path('fonts/'),
 
         /**
          * The location of a temporary directory.
@@ -56,7 +56,7 @@ return [
          * The temporary directory is required to download remote images and when
          * using the PFDLib back end.
          */
-        'DOMPDF_TEMP_DIR' => sys_get_temp_dir(),
+        'temp_dir' => sys_get_temp_dir(),
 
         /**
          * ==== IMPORTANT ====.
@@ -70,7 +70,7 @@ return [
          * direct class use like:
          * $dompdf = new DOMPDF();  $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
          */
-        'DOMPDF_CHROOT' => realpath(base_path()),
+        'chroot' => realpath(base_path()),
 
         /**
          * Whether to use Unicode fonts or not.
@@ -81,12 +81,12 @@ return [
          * When enabled, dompdf can support all Unicode glyphs. Any glyphs used in a
          * document must be present in your fonts, however.
          */
-        'DOMPDF_UNICODE_ENABLED' => true,
+        'unicode_enabled' => true,
 
         /**
          * Whether to enable font subsetting or not.
          */
-        'DOMPDF_ENABLE_FONTSUBSETTING' => false,
+        'enable_fontsubsetting' => false,
 
         /**
          * The PDF rendering backend to use.
@@ -115,7 +115,7 @@ return [
          * @link http://www.ros.co.nz/pdf
          * @link http://www.php.net/image
          */
-        'DOMPDF_PDF_BACKEND' => 'CPDF',
+        'pdf_backend' => 'CPDF',
 
         /**
          * PDFlib license key.
@@ -141,7 +141,7 @@ return [
          * the desired content might be different (e.g. screen or projection view of html file).
          * Therefore allow specification of content here.
          */
-        'DOMPDF_DEFAULT_MEDIA_TYPE' => 'print',
+        'default_media_type' => 'print',
 
         /**
          * The default paper size.
@@ -150,7 +150,7 @@ return [
          *
          * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
          */
-        'DOMPDF_DEFAULT_PAPER_SIZE' => 'a4',
+        'default_paper_size' => 'a4',
 
         /**
          * The default font family.
@@ -159,7 +159,7 @@ return [
          *
          * @var string
          */
-        'DOMPDF_DEFAULT_FONT' => 'dejavu sans',
+        'default_font' => 'dejavu sans',
 
         /**
          * Image DPI setting.
@@ -194,7 +194,7 @@ return [
          *
          * @var int
          */
-        'DOMPDF_DPI' => 96,
+        'dpi' => 96,
 
         /**
          * Enable inline PHP.
@@ -208,7 +208,7 @@ return [
          *
          * @var bool
          */
-        'DOMPDF_ENABLE_PHP' => false,
+        'enable_php' => false,
 
         /**
          * Enable inline Javascript.
@@ -218,7 +218,7 @@ return [
          *
          * @var bool
          */
-        'DOMPDF_ENABLE_JAVASCRIPT' => false,
+        'enable_javascript' => false,
 
         /**
          * Enable remote file access.
@@ -237,12 +237,12 @@ return [
          *
          * @var bool
          */
-        'DOMPDF_ENABLE_REMOTE' => true,
+        'enable_remote' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
 
         /**
          * A ratio applied to the fonts height to be more like browsers' line height.
          */
-        'DOMPDF_FONT_HEIGHT_RATIO' => 1.1,
+        'font_height_ratio' => 1.1,
 
         /**
          * Enable CSS float.
@@ -251,12 +251,12 @@ return [
          *
          * @var bool
          */
-        'DOMPDF_ENABLE_CSS_FLOAT' => true,
+        'enable_css_float' => true,
 
         /**
          * Use the more-than-experimental HTML5 Lib parser.
          */
-        'DOMPDF_ENABLE_HTML5PARSER' => true,
+        'enable_html5parser' => true,
 
     ],
 
index c299f9c71937cd279182249dbfa9d1aba3a79839..05d0ff13466ad81c9de1da4ee60b2373429e6dac 100644 (file)
@@ -140,7 +140,7 @@ class ExportFormatter
     protected function htmlToPdf(string $html): string
     {
         $containedHtml = $this->containHtml($html);
-        $useWKHTML = config('snappy.pdf.binary') !== false;
+        $useWKHTML = config('snappy.pdf.binary') !== false && config('app.allow_untrusted_server_fetching') === true;
         if ($useWKHTML) {
             $pdf = SnappyPDF::loadHTML($containedHtml);
             $pdf->setOption('print-media-type', true);
index 75c89ec335fb8cb1e7e3b42d5a483edf0b77dd25..7e0da05d42fb33a8a401af585609c53ee1af6659 100644 (file)
@@ -37,6 +37,7 @@
     <server name="LOG_CHANNEL" value="single"/>
     <server name="AUTH_METHOD" value="standard"/>
     <server name="DISABLE_EXTERNAL_SERVICES" value="true"/>
+    <server name="ALLOW_UNTRUSTED_SERVER_FETCHING" value="false"/>
     <server name="AVATAR_URL" value=""/>
     <server name="LDAP_START_TLS" value="false"/>
     <server name="LDAP_VERSION" value="3"/>
index 7031c3875a77edb925527d4dc4cd272d18111e55..aebc5f2455f31a2e2678df44371badabdd1cb89b 100644 (file)
@@ -366,4 +366,20 @@ class ExportTest extends TestCase
             $this->assertPermissionError($resp);
         }
     }
+
+    public function test_wkhtmltopdf_only_used_when_allow_untrusted_is_true()
+    {
+        /** @var Page $page */
+        $page = Page::query()->first();
+
+        config()->set('snappy.pdf.binary', '/abc123');
+        config()->set('app.allow_untrusted_server_fetching', false);
+
+        $resp = $this->asEditor()->get($page->getUrl('/export/pdf'));
+        $resp->assertStatus(200); // Sucessful response with invalid snappy binary indicates dompdf usage.
+
+        config()->set('app.allow_untrusted_server_fetching', true);
+        $resp = $this->get($page->getUrl('/export/pdf'));
+        $resp->assertStatus(500); // Bad response indicates wkhtml usage
+    }
 }
index f45d201363294274588d2e2ad318b8f970714a61..207fb7f59e3865aa607a6a36dc66696f1c63f835 100644 (file)
@@ -76,6 +76,12 @@ class ConfigTest extends TestCase
         );
     }
 
+    public function test_dompdf_remote_fetching_controlled_by_allow_untrusted_server_fetching_false()
+    {
+        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.defines.enable_remote', false);
+        $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.defines.enable_remote', true);
+    }
+
     /**
      * Set an environment variable of the given name and value
      * then check the given config key to see if it matches the given result.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.