CVE-2022-4877: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability has been found in snoyberg keter up to 1.8.1 and classified as problematic. This vulnerability affects unknown code of the file Keter/Proxy.hs. The manipulation of the argument host leads to cross site scripting. The attack can be initiated remotely. Upgrading to version 1.8.2 is able to address this issue. The name of the patch is d41f3697926b231782a3ad8050f5af1ce5cc40b7. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-217444.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-01-05T10:15Z
Repository: https://github.com/snoyberg/keter
Language: Other
Files changed: ChangeLog.md, Keter/Proxy.hs, keter.cabal
Commit date: 2022-04-19 09:17:31 -0400
Commit message: Fix potential xss issue in missing host response

The host field can be spoofed,
which allows an xss attack.
Eg you can put a bunch of javascript
(or whatever html) in the hostfield and
response to trick the user.
These chagnes make that impossible.

Diff: diff --git a/ChangeLog.md b/ChangeLog.md
index 604e2d7..1424ac0 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
+## 1.8.2 
+
++ Fix XSS issue in the default response.
+  (special thanks to Max @ulidtko for spotting and fixing this)
+
 ## 1.8.1
 
 + Fix haddock build
 
 ## 1.8
diff --git a/Keter/Proxy.hs b/Keter/Proxy.hs
index 8187346..abd1d01 100644
--- a/Keter/Proxy.hs
+++ b/Keter/Proxy.hs
@@ -11,11 +11,12 @@ module Keter.Proxy
     ) where
 
 import qualified Network.HTTP.Conduit      as HTTP
 import qualified Data.CaseInsensitive      as CI
 import qualified Keter.HostManager         as HostMan
-import           Blaze.ByteString.Builder          (copyByteString)
+import           Blaze.ByteString.Builder          (copyByteString, toByteString)
+import           Blaze.ByteString.Builder.Html.Word(fromHtmlEscapedByteString)
 import           Control.Applicative               ((<$>), (<|>))
 import           Control.Monad.IO.Class            (liftIO)
 import qualified Data.ByteString                   as S
 import qualified Data.ByteString.Char8             as S8
 import qualified Data.CaseInsensitive              as CI
@@ -282,12 +283,15 @@ missingHostResponse missingHost = Wai.responseBuilder
     $ copyByteString missingHost
 
 defaultUnknownHostBody :: ByteString -> ByteString
 defaultUnknownHostBody host =
   "<!DOCTYPE html>\n<html><head><title>Welcome to Keter</title></head><body><h1>Welcome to Keter</h1><p>The hostname you have provided, <code>"
-  <> host <> "</code>, is not recognized.</p></body></html>"
+  <> escapeHtml host <> "</code>, is not recognized.</p></body></html>"
 
 unknownHostResponse :: ByteString -> ByteString -> Wai.Response
 unknownHostResponse host body = Wai.responseBuilder
     status200
     [("Content-Type", "text/html; charset=utf-8"), ("X-Forwarded-Host", host)]
     (copyByteString body)
+
+escapeHtml :: ByteString -> ByteString
+escapeHtml = toByteString . fromHtmlEscapedByteString
diff --git a/keter.cabal b/keter.cabal
index 9a34c68..398835b 100644
--- a/keter.cabal
+++ b/keter.cabal
@@ -1,8 +1,8 @@
 Cabal-version:       >=1.10
 Name:                keter
-Version:             1.8.1
+Version:             1.8.2
 Synopsis:            Web application deployment manager, focusing on Haskell web frameworks
 Description:         Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/keter>.
 Homepage:            http://www.yesodweb.com/
 License:             MIT
 License-file:        LICENSE

Vulnerable code: import           Blaze.ByteString.Builder          (copyByteString)
  <> host <> "</code>, is not recognized.</p></body></html>"
Version:             1.8.1
Fixed code: ## 1.8.2 

+ Fix XSS issue in the default response.
  (special thanks to Max @ulidtko for spotting and fixing this)

import           Blaze.ByteString.Builder          (copyByteString, toByteString)
import           Blaze.ByteString.Builder.Html.Word(fromHtmlEscapedByteString)
  <> escapeHtml host <> "</code>, is not recognized.</p></body></html>"

escapeHtml :: ByteString -> ByteString
escapeHtml = toByteString . fromHtmlEscapedByteString
Version:             1.8.2