Package: release.debian.org Severity: normal Tags: bullseye User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: pan...@packages.debian.org, Guilhem Moulin <guil...@debian.org> Control: affects -1 + src:pandoc
[ Reason ] pandoc 2.9.2.1-1 is vulnerable to CVE-2023-35936: Arbitrary file write vulnerability via specially crafted image element in the input when generating files using the `--extract-media` option or outputting to PDF format. The Security Team decided not to issue a DSA for that CVE, but it's now fixed in buster-security (2.2.1-3+deb10u1) as well as sid (2.17.1.1-2), so it makes sense to fix it via (o)s-pu too. [ Impact ] For users uprading from buster-security to bullseye, that would be a security regression. [ Tests ] A new unit test was added upstream, and backported along with the code fixes. The test suite is now run at build time (this was not the case before due to #1010179 — in fact some unit tests had to be updated for the suite to pass). I also manually verified that the PoC were fixed. [ Risks ] The upstream fixes were not trivial to backport due to major refactoring, but test coverage is good. (Upstream changes to pandoc.cabal are a no-op as far as debian packaging is concerned.) [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in oldstable [x] the issue is verified as fixed in unstable [ Changes ] * Add d/salsa-ci.yml for Salsa CI. * Fix upstream test suite and make sure it is run at build time (cf. #1010179). * Fix CVE-2023-35936 and CVE-2023-38745: Arbitrary file write vulnerability via specially crafted image element in the input when generating files using the `--extract-media` option or outputting to PDF format. (Closes: #1041976) -- Guilhem.
diffstat for pandoc-2.9.2.1 pandoc-2.9.2.1 changelog | 13 + patches/2001_templates_avoid_privacy_breach.patch | 72 ++++++++++- patches/Adjust-tests.patch | 133 ++++++++++++++++++++ patches/CVE-2023-35936.patch | 144 ++++++++++++++++++++++ patches/CVE-2023-38745.patch | 92 ++++++++++++++ patches/series | 3 rules | 2 salsa-ci.yml | 8 + 8 files changed, 462 insertions(+), 5 deletions(-) diff -Nru pandoc-2.9.2.1/debian/changelog pandoc-2.9.2.1/debian/changelog --- pandoc-2.9.2.1/debian/changelog 2020-08-23 10:24:33.000000000 +0200 +++ pandoc-2.9.2.1/debian/changelog 2023-07-21 19:59:53.000000000 +0200 @@ -1,3 +1,16 @@ +pandoc (2.9.2.1-1+deb11u1) bullseye; urgency=high + + * Non-maintainer upload. + * Add d/salsa-ci.yml for Salsa CI. + * Fix upstream test suite and make sure it is run at build time (cf. + #1010179). + * Fix CVE-2023-35936 and CVE-2023-38745: Arbitrary file write vulnerability + via specially crafted image element in the input when generating files + using the `--extract-media` option or outputting to PDF format. (Closes: + #1041976) + + -- Guilhem Moulin <guil...@debian.org> Fri, 21 Jul 2023 19:59:53 +0200 + pandoc (2.9.2.1-1) unstable; urgency=medium [ upstream ] diff -Nru pandoc-2.9.2.1/debian/patches/2001_templates_avoid_privacy_breach.patch pandoc-2.9.2.1/debian/patches/2001_templates_avoid_privacy_breach.patch --- pandoc-2.9.2.1/debian/patches/2001_templates_avoid_privacy_breach.patch 2020-08-23 09:39:53.000000000 +0200 +++ pandoc-2.9.2.1/debian/patches/2001_templates_avoid_privacy_breach.patch 2023-07-21 19:59:53.000000000 +0200 @@ -1,9 +1,12 @@ Description: Avoid potential privacy breaches in templates Author: Jonas Smedegaard <d...@jones.dk> License: GPL-3+ -Last-Update: 2018-06-12 +Last-Update: 2023-07-21 --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +diff --git a/data/dzslides/template.html b/data/dzslides/template.html +index 56ef896..c3c4c9e 100644 --- a/data/dzslides/template.html +++ b/data/dzslides/template.html @@ -48,7 +48,7 @@ @@ -42,9 +45,11 @@ font-size: 30px; } +diff --git a/data/templates/default.dzslides b/data/templates/default.dzslides +index 11103ab..21bb8fa 100644 --- a/data/templates/default.dzslides +++ b/data/templates/default.dzslides -@@ -20,15 +20,12 @@ +@@ -20,15 +20,12 @@ $for(css)$ <link rel="stylesheet" href="$css$"> $endfor$ $else$ @@ -61,9 +66,11 @@ font-size: 30px; } +diff --git a/data/templates/default.html5 b/data/templates/default.html5 +index 0676215..724cde4 100644 --- a/data/templates/default.html5 +++ b/data/templates/default.html5 -@@ -23,9 +23,6 @@ +@@ -23,9 +23,6 @@ $endfor$ $if(math)$ $math$ $endif$ @@ -73,9 +80,11 @@ $for(header-includes)$ $header-includes$ $endfor$ +diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs +index fde8a9a..c40c3ec 100644 --- a/src/Text/Pandoc/Options.hs +++ b/src/Text/Pandoc/Options.hs -@@ -308,10 +308,10 @@ +@@ -308,10 +308,10 @@ isEnabled :: HasSyntaxExtensions a => Extension -> a -> Bool isEnabled ext opts = ext `extensionEnabled` getExtensions opts defaultMathJaxURL :: Text @@ -88,3 +97,58 @@ $(deriveJSON defaultOptions ''ReaderOptions) +diff --git a/test/lhs-test.html b/test/lhs-test.html +index 8153a4b..6bde36c 100644 +--- a/test/lhs-test.html ++++ b/test/lhs-test.html +@@ -75,9 +75,6 @@ + code span.vs { color: #4070a0; } /* VerbatimString */ + code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ + </style> +- <!--[if lt IE 9]> +- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> +- <![endif]--> + </head> + <body> + <h1 id="lhs-test">lhs test</h1> +diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs +index 0ada9fa..e86bfd6 100644 +--- a/test/lhs-test.html+lhs ++++ b/test/lhs-test.html+lhs +@@ -75,9 +75,6 @@ + code span.vs { color: #4070a0; } /* VerbatimString */ + code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ + </style> +- <!--[if lt IE 9]> +- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> +- <![endif]--> + </head> + <body> + <h1 id="lhs-test">lhs test</h1> +diff --git a/test/s5-fancy.html b/test/s5-fancy.html +index 7f5350b..23892c8 100644 +--- a/test/s5-fancy.html ++++ b/test/s5-fancy.html +@@ -28,7 +28,7 @@ + <link rel="stylesheet" href="s5/default/opera.css" type="text/css" media="projection" id="operaFix" /> + <!-- S5 JS --> + <script src="s5/default/slides.js" type="text/javascript"></script> +- <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" type="text/javascript"></script> ++ <script src="/usr/share/javascript/mathjax/tex-mml-chtml.js" type="text/javascript"></script> + </head> + <body> + <div class="layout"> +diff --git a/test/writer.html5 b/test/writer.html5 +index 431503b..859f8b9 100644 +--- a/test/writer.html5 ++++ b/test/writer.html5 +@@ -16,9 +16,6 @@ + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} + ul.task-list{list-style: none;} + </style> +- <!--[if lt IE 9]> +- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> +- <![endif]--> + </head> + <body> + <header id="title-block-header"> diff -Nru pandoc-2.9.2.1/debian/patches/Adjust-tests.patch pandoc-2.9.2.1/debian/patches/Adjust-tests.patch --- pandoc-2.9.2.1/debian/patches/Adjust-tests.patch 1970-01-01 01:00:00.000000000 +0100 +++ pandoc-2.9.2.1/debian/patches/Adjust-tests.patch 2023-07-21 19:59:53.000000000 +0200 @@ -0,0 +1,133 @@ +From: John MacFarlane <j...@berkeley.edu> +Date: Tue, 12 May 2020 13:51:48 -0700 +Subject: Use latest skylighting. + +This adds `aria-hidden="true"` to the empty a elements, which +helps people who use screen readers. + +Origin: https://github.com/jgm/pandoc/commit/8d0c124e5f76af6aa08acf9b0c526822f65e232b +Origin: https://github.com/jgm/pandoc/commit/112e98def6baf3433e99fbaa3e7280cad16f5422 +--- + pandoc.cabal | 4 ++-- + stack.yaml | 4 ++-- + test/command/5627.md | 8 ++++---- + test/command/5650.md | 8 ++++---- + test/lhs-test.html | 6 +++--- + test/lhs-test.html+lhs | 6 +++--- + 6 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/pandoc.cabal b/pandoc.cabal +index f6c03a0..a8b9f8e 100644 +--- a/pandoc.cabal ++++ b/pandoc.cabal +@@ -404,8 +404,8 @@ library + tagsoup >= 0.14.6 && < 0.15, + base64-bytestring >= 0.1 && < 1.1, + zlib >= 0.5 && < 0.7, +- skylighting >= 0.8.3.2 && < 0.9, +- skylighting-core >= 0.8.3.2 && < 0.9, ++ skylighting >= 0.8.5 && < 0.9, ++ skylighting-core >= 0.8.5 && < 0.9, + data-default >= 0.4 && < 0.8, + temporary >= 1.1 && < 1.4, + blaze-html >= 0.9 && < 0.10, +diff --git a/stack.yaml b/stack.yaml +index b56beb7..92a80f7 100644 +--- a/stack.yaml ++++ b/stack.yaml +@@ -15,8 +15,8 @@ extra-deps: + - pandoc-types-1.20 + - texmath-0.12.0.1 + - haddock-library-1.8.0 +-- skylighting-0.8.3.2 +-- skylighting-core-0.8.3.2 ++- skylighting-0.8.5 ++- skylighting-core-0.8.5 + - regex-pcre-builtin-0.95.0.8.8.35 + - doclayout-0.3 + - emojis-0.1 +diff --git a/test/command/5627.md b/test/command/5627.md +index 0f67a08..41fec00 100644 +--- a/test/command/5627.md ++++ b/test/command/5627.md +@@ -20,8 +20,8 @@ Something + <li>Two <code>-->something<!--</code></li> + <li>Three</li> + </ol> +-<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1"></a>--><span class="co"><!--<script>alert('Escaped!')</script></span></span></code></pre></div> +-<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1"></a>Something</span></code></pre></div> ++<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>--><span class="co"><!--<script>alert('Escaped!')</script></span></span></code></pre></div> ++<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>Something</span></code></pre></div> + ``` + + ``` +@@ -46,8 +46,8 @@ Something + <li><code>-->something<!--</code></li> + <li>bye <code>-->something else<!--</code></li> + </ul> +-<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1"></a>--><span class="co"><!--<script>alert('Escaped!')</script></span></span></code></pre></div> +-<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1"></a>Something</span></code></pre></div> ++<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>--><span class="co"><!--<script>alert('Escaped!')</script></span></span></code></pre></div> ++<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>Something</span></code></pre></div> + ``` + + ``` +diff --git a/test/command/5650.md b/test/command/5650.md +index 0618f41..2f36c60 100644 +--- a/test/command/5650.md ++++ b/test/command/5650.md +@@ -5,8 +5,8 @@ a + b + ``` + ^D +-<div class="sourceCode" id="foocb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foocb1-1"><a href="#foocb1-1"></a>a</span> +-<span id="foocb1-2"><a href="#foocb1-2"></a>b</span></code></pre></div> ++<div class="sourceCode" id="foocb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foocb1-1"><a href="#foocb1-1" aria-hidden="true"></a>a</span> ++<span id="foocb1-2"><a href="#foocb1-2" aria-hidden="true"></a>b</span></code></pre></div> + ```` + + ```` +@@ -16,7 +16,7 @@ a + b + ``` + ^D +-<div class="sourceCode" id="foobar"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foobar-1"><a href="#foobar-1"></a>a</span> +-<span id="foobar-2"><a href="#foobar-2"></a>b</span></code></pre></div> ++<div class="sourceCode" id="foobar"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="foobar-1"><a href="#foobar-1" aria-hidden="true"></a>a</span> ++<span id="foobar-2"><a href="#foobar-2" aria-hidden="true"></a>b</span></code></pre></div> + ```` + +diff --git a/test/lhs-test.html b/test/lhs-test.html +index 6bde36c..43ff13e 100644 +--- a/test/lhs-test.html ++++ b/test/lhs-test.html +@@ -80,9 +80,9 @@ + <h1 id="lhs-test">lhs test</h1> + <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to + return a single value:</p> +-<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1"></a><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=></span> (b <span class="ot">-></span> c <span class="ot">-></span> d) <span class="ot">-></span> a (b, c) d</span> +-<span id="cb1-2"><a href="#cb1-2"></a>unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span> +-<span id="cb1-3"><a href="#cb1-3"></a> <span class="co">-- arr (\op (x,y) -> x `op` y)</span></span></code></pre></div> ++<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=></span> (b <span class="ot">-></span> c <span class="ot">-></span> d) <span class="ot">-></span> a (b, c) d</span> ++<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span> ++<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a> <span class="co">-- arr (\op (x,y) -> x `op` y)</span></span></code></pre></div> + <p><code>(***)</code> combines two arrows into a new arrow by running the two arrows on a + pair of values (one arrow on the first item of the pair and one arrow on the + second item of the pair).</p> +diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs +index e86bfd6..8cdf3f2 100644 +--- a/test/lhs-test.html+lhs ++++ b/test/lhs-test.html+lhs +@@ -80,9 +80,9 @@ + <h1 id="lhs-test">lhs test</h1> + <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to + return a single value:</p> +-<div class="sourceCode" id="cb1"><pre class="sourceCode literatehaskell literate"><code class="sourceCode literatehaskell"><span id="cb1-1"><a href="#cb1-1"></a><span class="ot">> unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=></span> (b <span class="ot">-></span> c <span class="ot">-></span> d) <span class="ot">-></span> a (b, c) d</span> +-<span id="cb1-2"><a href="#cb1-2"></a><span class="ot">></span> unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span> +-<span id="cb1-3"><a href="#cb1-3"></a><span class="ot">></span> <span class="co">-- arr (\op (x,y) -> x `op` y)</span></span></code></pre></div> ++<div class="sourceCode" id="cb1"><pre class="sourceCode literatehaskell literate"><code class="sourceCode literatehaskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ot">> unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=></span> (b <span class="ot">-></span> c <span class="ot">-></span> d) <span class="ot">-></span> a (b, c) d</span> ++<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="ot">></span> unsplit <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">uncurry</span></span> ++<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a><span class="ot">></span> <span class="co">-- arr (\op (x,y) -> x `op` y)</span></span></code></pre></div> + <p><code>(***)</code> combines two arrows into a new arrow by running the two arrows on a + pair of values (one arrow on the first item of the pair and one arrow on the + second item of the pair).</p> diff -Nru pandoc-2.9.2.1/debian/patches/CVE-2023-35936.patch pandoc-2.9.2.1/debian/patches/CVE-2023-35936.patch --- pandoc-2.9.2.1/debian/patches/CVE-2023-35936.patch 1970-01-01 01:00:00.000000000 +0100 +++ pandoc-2.9.2.1/debian/patches/CVE-2023-35936.patch 2023-07-21 19:59:53.000000000 +0200 @@ -0,0 +1,144 @@ +From: John MacFarlane <j...@berkeley.edu> +Date: Tue, 20 Jun 2023 13:50:13 -0700 +Subject: Fix a security vulnerability in MediaBag and + T.P.Class.IO.writeMedia. + +This vulnerability, discovered by Entroy C, allows users to write +arbitrary files to any location by feeding pandoc a specially crafted +URL in an image element. The vulnerability is serious for anyone +using pandoc to process untrusted input. + +Origin: https://github.com/jgm/pandoc/commit/5e381e3878b5da87ee7542f7e51c3c1a7fd84b89 +Origin: https://github.com/jgm/pandoc/commit/54561e9a6667b36a8452b01d2def9e3642013dd6 +Origin: https://github.com/jgm/pandoc/commit/df4f13b262f7be5863042f8a5a1c365282c81f07 +Origin: https://github.com/jgm/pandoc/commit/fe62da61dfd33e6b4c0c03895c528a47a0405bf7 +Origin: https://github.com/jgm/pandoc/commit/5246f02f0bb9c176a6d2f6e3d0c03407d8a67445 +Bug: https://github.com/jgm/pandoc/security/advisories/GHSA-xj5q-fv23-575g +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-35936 +--- + pandoc.cabal | 1 + + src/Text/Pandoc/Class/PandocIO.hs | 12 ++++++------ + src/Text/Pandoc/Class/PandocMonad.hs | 2 +- + test/Tests/MediaBag.hs | 37 ++++++++++++++++++++++++++++++++++++ + test/test-pandoc.hs | 2 ++ + 5 files changed, 47 insertions(+), 7 deletions(-) + create mode 100644 test/Tests/MediaBag.hs + +diff --git a/pandoc.cabal b/pandoc.cabal +index a8b9f8e..04ab218 100644 +--- a/pandoc.cabal ++++ b/pandoc.cabal +@@ -762,6 +762,7 @@ test-suite test-pandoc + Tests.Lua + Tests.Lua.Module + Tests.Shared ++ Tests.MediaBag + Tests.Readers.LaTeX + Tests.Readers.HTML + Tests.Readers.JATS +diff --git a/src/Text/Pandoc/Class/PandocIO.hs b/src/Text/Pandoc/Class/PandocIO.hs +index 1cbfd68..0472816 100644 +--- a/src/Text/Pandoc/Class/PandocIO.hs ++++ b/src/Text/Pandoc/Class/PandocIO.hs +@@ -57,7 +57,7 @@ import Network.HTTP.Client.Internal (addProxy) + import Network.HTTP.Client.TLS (tlsManagerSettings) + import Network.HTTP.Types.Header ( hContentType ) + import Network.Socket (withSocketsDo) +-import Network.URI ( unEscapeString ) ++import Network.URI (URI(..), parseURI, unEscapeString) + import Prelude + import System.Directory (createDirectoryIfMissing) + import System.Environment (getEnv) +@@ -131,11 +131,11 @@ instance PandocMonad PandocIO where + newUniqueHash = hashUnique <$> liftIO IO.newUnique + + openURL u +- | Just u'' <- T.stripPrefix "data:" u = do +- let mime = T.takeWhile (/=',') u'' +- let contents = UTF8.fromString $ +- unEscapeString $ T.unpack $ T.drop 1 $ T.dropWhile (/=',') u'' +- return (decodeLenient contents, Just mime) ++ | Just (URI{ uriScheme = "data:", ++ uriPath = upath }) <- parseURI (T.unpack u) = do ++ let (mime, rest) = break (== ',') $ unEscapeString upath ++ let contents = UTF8.fromString $ drop 1 rest ++ return (decodeLenient contents, Just (T.pack mime)) + | otherwise = do + let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v) + customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders +diff --git a/src/Text/Pandoc/Class/PandocMonad.hs b/src/Text/Pandoc/Class/PandocMonad.hs +index 8229668..eb6bedd 100644 +--- a/src/Text/Pandoc/Class/PandocMonad.hs ++++ b/src/Text/Pandoc/Class/PandocMonad.hs +@@ -612,7 +612,7 @@ fetchMediaResource :: PandocMonad m + => T.Text -> m (FilePath, Maybe MimeType, BL.ByteString) + fetchMediaResource src = do + (bs, mt) <- downloadOrRead src +- let ext = fromMaybe (T.pack $ takeExtension $ T.unpack src) ++ let ext = fromMaybe (T.pack $ takeExtension $ unEscapeString $ T.unpack src) + (mt >>= extensionFromMimeType) + let bs' = BL.fromChunks [bs] + let basename = showDigest $ sha1 bs' +diff --git a/test/Tests/MediaBag.hs b/test/Tests/MediaBag.hs +new file mode 100644 +index 0000000..8a57337 +--- /dev/null ++++ b/test/Tests/MediaBag.hs +@@ -0,0 +1,37 @@ ++{-# LANGUAGE OverloadedStrings #-} ++module Tests.MediaBag (tests) where ++ ++import Test.Tasty ++import Test.Tasty.HUnit ++-- import Tests.Helpers ++import Text.Pandoc.Class (extractMedia, fillMediaBag, runIOorExplode) ++import System.IO.Temp (withTempDirectory) ++import Text.Pandoc.Shared (inDirectory) ++import System.FilePath ++import Text.Pandoc.Builder as B ++import System.Directory (doesFileExist, copyFile) ++ ++tests :: [TestTree] ++tests = [ ++ testCase "test fillMediaBag & extractMedia" $ ++ withTempDirectory "." "extractMediaTest" $ \tmpdir -> inDirectory tmpdir $ do ++ copyFile "../../test/bodybg.gif" "bodybg.gif" ++ let d = B.doc $ ++ B.para (B.image "../../test/lalune.jpg" "" mempty) <> ++ B.para (B.image "bodybg.gif" "" mempty) <> ++ B.para (B.image "data://image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <> ++ B.para (B.image "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" "" mempty) ++ runIOorExplode $ do ++ fillMediaBag d ++ extractMedia "foo" d ++ exists1 <- doesFileExist ("foo" </> "278e30c6961bc3e263c638fb15e114d35290db05.gif") ++ assertBool "file in directory is not extracted with hashed name" exists1 ++ exists2 <- doesFileExist ("foo" </> "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg") ++ assertBool "file above directory is not extracted with hashed name" exists2 ++ exists3 <- doesFileExist ("foo" </> "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.lua") ++ exists4 <- doesFileExist "a.lua" ++ assertBool "data uri with malicious payload gets written outside of destination dir" ++ (exists3 && not exists4) ++ exists5 <- doesFileExist ("foo" </> "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif") ++ assertBool "data uri with gif is not properly decoded" exists5 ++ ] +diff --git a/test/test-pandoc.hs b/test/test-pandoc.hs +index 9d64b61..b1804dd 100644 +--- a/test/test-pandoc.hs ++++ b/test/test-pandoc.hs +@@ -44,6 +44,7 @@ import qualified Tests.Writers.Powerpoint + import qualified Tests.Writers.RST + import qualified Tests.Writers.TEI + import Tests.Helpers (findPandoc) ++import qualified Tests.MediaBag + import Text.Pandoc.Shared (inDirectory) + + tests :: FilePath -> TestTree +@@ -51,6 +52,7 @@ tests pandocPath = testGroup "pandoc tests" + [ Tests.Command.tests pandocPath + , testGroup "Old" (Tests.Old.tests pandocPath) + , testGroup "Shared" Tests.Shared.tests ++ , testGroup "MediaBag" Tests.MediaBag.tests + , testGroup "Writers" + [ testGroup "Native" Tests.Writers.Native.tests + , testGroup "ConTeXt" Tests.Writers.ConTeXt.tests diff -Nru pandoc-2.9.2.1/debian/patches/CVE-2023-38745.patch pandoc-2.9.2.1/debian/patches/CVE-2023-38745.patch --- pandoc-2.9.2.1/debian/patches/CVE-2023-38745.patch 1970-01-01 01:00:00.000000000 +0100 +++ pandoc-2.9.2.1/debian/patches/CVE-2023-38745.patch 2023-07-21 19:59:53.000000000 +0200 @@ -0,0 +1,92 @@ +From: John MacFarlane <j...@berkeley.edu> +Date: Thu, 20 Jul 2023 09:26:38 -0700 +Subject: Fix new variant of the vulnerability in CVE-2023-35936. + +Guilhem Moulin noticed that the fix to CVE-2023-35936 was incomplete. +An attacker could get around it by double-encoding the malicious +extension to create or override arbitrary files. + + $ echo '![](data://image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%252f%252e%252e%252f%252e%252e%252fb%252elua)' >b.md + $ .cabal/bin/pandoc b.md --extract-media=bar + <p><img + src="bar/2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.lua+%2f%2e%2e%2f%2e%2e%2fb%2elua" /></p> + $ cat b.lua + print "hello" + $ find bar + bar/ + bar/2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.lua+ + +This commit adds a test case for this more complex attack and fixes +the vulnerability. + +Origin: https://github.com/jgm/pandoc/commit/eddedbfc14916aa06fc01ff04b38aeb30ae2e625 +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-38745 +--- + src/Text/Pandoc/Class/PandocMonad.hs | 10 +++++----- + test/Tests/MediaBag.hs | 12 +++++++++++- + 2 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/src/Text/Pandoc/Class/PandocMonad.hs b/src/Text/Pandoc/Class/PandocMonad.hs +index eb6bedd..13fd7c2 100644 +--- a/src/Text/Pandoc/Class/PandocMonad.hs ++++ b/src/Text/Pandoc/Class/PandocMonad.hs +@@ -56,14 +56,13 @@ import Codec.Archive.Zip + import Control.Monad.Except (MonadError (catchError, throwError), + MonadTrans, lift, when) + import Data.Digest.Pure.SHA (sha1, showDigest) +-import Data.Maybe (fromMaybe) + import Data.Time (UTCTime) + import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds) + import Data.Time.LocalTime (TimeZone, ZonedTime, utcToZonedTime) + import Network.URI ( escapeURIString, nonStrictRelativeTo, + unEscapeString, parseURIReference, isAllowedInURI, + parseURI, URI(..) ) +-import System.FilePath ((</>), (<.>), takeExtension, dropExtension, ++import System.FilePath ((</>), takeExtension, dropExtension, + isRelative, splitDirectories) + import System.Random (StdGen) + import Text.Pandoc.BCP47 (Lang(..), parseBCP47, renderLang) +@@ -612,11 +611,12 @@ fetchMediaResource :: PandocMonad m + => T.Text -> m (FilePath, Maybe MimeType, BL.ByteString) + fetchMediaResource src = do + (bs, mt) <- downloadOrRead src +- let ext = fromMaybe (T.pack $ takeExtension $ unEscapeString $ T.unpack src) +- (mt >>= extensionFromMimeType) ++ let ext = case (takeExtension $ unEscapeString $ T.unpack src) of ++ '.':e | '%' `notElem` e -> '.':e ++ _ -> maybe "" (\x -> '.':T.unpack x) (mt >>= extensionFromMimeType) + let bs' = BL.fromChunks [bs] + let basename = showDigest $ sha1 bs' +- let fname = basename <.> T.unpack ext ++ let fname = basename <> ext + return (fname, mt, bs') + + -- | Traverse tree, filling media bag for any images that +diff --git a/test/Tests/MediaBag.hs b/test/Tests/MediaBag.hs +index 8a57337..ffba89f 100644 +--- a/test/Tests/MediaBag.hs ++++ b/test/Tests/MediaBag.hs +@@ -19,7 +19,7 @@ tests = [ + let d = B.doc $ + B.para (B.image "../../test/lalune.jpg" "" mempty) <> + B.para (B.image "bodybg.gif" "" mempty) <> +- B.para (B.image "data://image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <> ++ B.para (B.image "data:image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <> + B.para (B.image "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" "" mempty) + runIOorExplode $ do + fillMediaBag d +@@ -34,4 +34,14 @@ tests = [ + (exists3 && not exists4) + exists5 <- doesFileExist ("foo" </> "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif") + assertBool "data uri with gif is not properly decoded" exists5 ++ -- double-encoded version: ++ let e = B.doc $ ++ B.para (B.image "data:image/png;base64,cHJpbnQgInB3bmVkIgo=;.lua+%252f%252e%252e%252f%252e%252e%252fb%252elua" "" mempty) ++ runIOorExplode $ do ++ fillMediaBag e ++ extractMedia "bar" e ++ exists6 <- doesFileExist ("bar" </> "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png") ++ exists7 <- doesFileExist "b.lua" ++ assertBool "data uri with double-encoded malicious payload gets written outside of destination dir" ++ (exists6 && not exists7) + ] diff -Nru pandoc-2.9.2.1/debian/patches/series pandoc-2.9.2.1/debian/patches/series --- pandoc-2.9.2.1/debian/patches/series 2020-08-23 10:15:20.000000000 +0200 +++ pandoc-2.9.2.1/debian/patches/series 2023-07-21 19:59:53.000000000 +0200 @@ -1,3 +1,6 @@ 020200417~a9ef15b.patch 2001_templates_avoid_privacy_breach.patch 2002_program_package_hint.patch +Adjust-tests.patch +CVE-2023-35936.patch +CVE-2023-38745.patch diff -Nru pandoc-2.9.2.1/debian/rules pandoc-2.9.2.1/debian/rules --- pandoc-2.9.2.1/debian/rules 2020-08-23 09:35:10.000000000 +0200 +++ pandoc-2.9.2.1/debian/rules 2023-07-21 19:59:53.000000000 +0200 @@ -1,5 +1,6 @@ #!/usr/bin/make -f +export DEB_ENABLE_TESTS = yes include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/hlibrary.mk @@ -182,7 +183,6 @@ DEB_SETUP_GHC_CONFIGURE_ARGS += --ghc-options="-optc--param -optcggc-min-expand=10 -O0" endif -DEB_ENABLE_TESTS = yes DEB_SETUP_GHC_CONFIGURE_ARGS += $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,-ftests) DEB_INSTALL_DOCS_ALL += README.md diff -Nru pandoc-2.9.2.1/debian/salsa-ci.yml pandoc-2.9.2.1/debian/salsa-ci.yml --- pandoc-2.9.2.1/debian/salsa-ci.yml 1970-01-01 01:00:00.000000000 +0100 +++ pandoc-2.9.2.1/debian/salsa-ci.yml 2023-07-21 19:59:53.000000000 +0200 @@ -0,0 +1,8 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml + +variables: + RELEASE: 'bullseye' + SALSA_CI_DISABLE_REPROTEST: 1 + SALSA_CI_DISABLE_LINTIAN: 1
signature.asc
Description: PGP signature