Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow crlf headers #92 #359

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Web/Scotty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ module Web.Scotty
, pathParams, captureParams, formParams, queryParams
, jsonData, files
-- ** Modifying the Response and Redirecting
, status, addHeader, setHeader, redirect
-- *** Status
, status
-- *** Headers
, addHeader, setHeader
, addHeader1, setHeader1
, redirect
-- ** Setting Response Body
--
-- | Note: only one of these should be present in any given route
Expand Down Expand Up @@ -358,6 +363,20 @@ addHeader = Trans.addHeader
setHeader :: Text -> Text -> ActionM ()
setHeader = Trans.setHeader

-- | Add to the response headers. Header names are case-insensitive.
addHeader1 :: Text -- ^ Header name
-> Text -- ^ Header value. Only the first characters before a newline or carrier return are kept
-> ActionM ()
addHeader1 = Trans.addHeader1

-- | Set one of the response headers. Will override any previously set value for that header.
-- Header names are case-insensitive.
setHeader1 :: Text -- ^ Header name
-> Text -- ^ Header value. Only the first characters before a newline or carrier return are kept
-> ActionM ()
setHeader1 = Trans.setHeader1


-- | Set the body of the response to the given 'Text' value. Also sets \"Content-Type\"
-- header to \"text/plain; charset=utf-8\" if it has not already been set.
text :: Text -> ActionM ()
Expand Down
26 changes: 26 additions & 0 deletions Web/Scotty/Action.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
{-# language ScopedTypeVariables #-}
module Web.Scotty.Action
( addHeader
, addHeader1
, body
, bodyReader
, file
Expand Down Expand Up @@ -45,6 +46,7 @@
, request
, rescue
, setHeader
, setHeader1
, status
, stream
, text
Expand Down Expand Up @@ -92,7 +94,7 @@
import Numeric.Natural

import Web.Scotty.Internal.Types
import Web.Scotty.Util (mkResponse, addIfNotPresent, add, replace, lazyTextToStrictByteString, decodeUtf8Lenient)

Check warning on line 97 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

The import of ‘decodeUtf8Lenient’

Check warning on line 97 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

The import of ‘decodeUtf8Lenient’

Check warning on line 97 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

The import of ‘decodeUtf8Lenient’
import UnliftIO.Exception (Handler(..), catch, catches, throwIO)

import Network.Wai.Internal (ResponseReceived(..))
Expand All @@ -119,7 +121,7 @@
-- | Catches 'StatusError' and produces an appropriate HTTP response.
statusErrorHandler :: MonadIO m => ErrorHandler m
statusErrorHandler = Handler $ \case
StatusError s e -> do

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of data constructor ‘StatusError’

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of data constructor ‘StatusError’

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of data constructor ‘StatusError’

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of data constructor ‘StatusError’

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of data constructor ‘StatusError’

Check warning on line 124 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of data constructor ‘StatusError’
status s
let code = T.pack $ show $ statusCode s
let msg = decodeUtf8Lenient $ statusMessage s
Expand Down Expand Up @@ -186,7 +188,7 @@
--
-- Uncaught exceptions turn into HTTP responses corresponding to the given status.
raiseStatus :: Monad m => Status -> T.Text -> ActionT m a
raiseStatus s = E.throw . StatusError s

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of data constructor ‘StatusError’

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of data constructor ‘StatusError’

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of data constructor ‘StatusError’

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of data constructor ‘StatusError’

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of data constructor ‘StatusError’

Check warning on line 191 in Web/Scotty/Action.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of data constructor ‘StatusError’
{-# DEPRECATED raiseStatus "Use status, text, and finish instead" #-}

-- | Throw an exception which can be caught within the scope of the current Action with 'catch'.
Expand Down Expand Up @@ -539,14 +541,38 @@
changeHeader f k =
modifyResponse . setHeaderWith . f (CI.mk $ encodeUtf8 k) . encodeUtf8

-- like 'changeHeader' but chops off all header values after the first CR or LF
changeHeader1 :: MonadIO m =>
(CI.CI B.ByteString -> B.ByteString -> [(HeaderName, B.ByteString)] -> [(HeaderName, B.ByteString)])
-> T.Text -> T.Text -> ActionT m ()
changeHeader1 f k v0 = case splitAtCRLF (encodeUtf8 v0) of
Nothing -> pure ()
Just v -> modifyResponse $ setHeaderWith $ f (CI.mk $ encodeUtf8 k) v

-- | Add to the response headers. Header names are case-insensitive.
addHeader1 :: MonadIO m => T.Text -- ^ Header name
-> T.Text -- ^ Header value. Only the first characters before a newline or carrier return are kept
-> ActionT m ()
addHeader1 = changeHeader1 add

-- | Set one of the response headers. Will override any previously set value for that header.
-- Header names are case-insensitive.
setHeader1 :: MonadIO m => T.Text -- ^ Header name
-> T.Text -- ^ Header value. Only the first characters before a newline or carrier return are kept
-> ActionT m ()
setHeader1 = changeHeader1 replace


-- | Add to the response headers. Header names are case-insensitive.
addHeader :: MonadIO m => T.Text -> T.Text -> ActionT m ()
addHeader = changeHeader add
{-# DEPRECATED addHeader "this function does not validate header values and can potentially lead to security problems (e.g. response splitting attacks). Please use addHeader1 instead (#92)" #-}

-- | Set one of the response headers. Will override any previously set value for that header.
-- Header names are case-insensitive.
setHeader :: MonadIO m => T.Text -> T.Text -> ActionT m ()
setHeader = changeHeader replace
{-# DEPRECATED setHeader "this function does not validate header values and can potentially lead to security problems (e.g. response splitting attacks). Please use setHeader1 instead (#92)" #-}

-- | Set the body of the response to the given 'T.Text' value. Also sets \"Content-Type\"
-- header to \"text/plain; charset=utf-8\" if it has not already been set.
Expand Down
34 changes: 31 additions & 3 deletions Web/Scotty/Cookie.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
-- * Set cookie
setCookie
, setSimpleCookie
-- ** Sanitized values
, setCookie1
, setSimpleCookie1
-- * Get cookie(s)
, getCookie
, getCookies
Expand Down Expand Up @@ -79,7 +82,7 @@
-- cookie
import Web.Cookie (SetCookie, setCookieName , setCookieValue, setCookiePath, setCookieExpires, setCookieMaxAge, setCookieDomain, setCookieHttpOnly, setCookieSecure, setCookieSameSite, renderSetCookie, defaultSetCookie, CookiesText, parseCookiesText, SameSiteOption, sameSiteStrict, sameSiteNone, sameSiteLax)
-- scotty
import Web.Scotty.Action (ActionT, addHeader, header)
import Web.Scotty.Action (ActionT, addHeader, header, addHeader1, setHeader, setHeader1)

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

The import of ‘addHeader, addHeader1’

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

The import of ‘addHeader, addHeader1’

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

The import of ‘addHeader, addHeader1’

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

The import of ‘addHeader, addHeader1’

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

The import of ‘addHeader, addHeader1’

Check warning on line 85 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

The import of ‘addHeader, addHeader1’
-- time
import Data.Time.Clock.POSIX ( posixSecondsToUTCTime )
-- text
Expand All @@ -91,19 +94,44 @@
setCookie :: (MonadIO m)
=> SetCookie
-> ActionT m ()
setCookie c = addHeader "Set-Cookie"
setCookie = setCookieWith setHeader

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of ‘setHeader’ (imported from Web.Scotty.Action):

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of ‘setHeader’ (imported from Web.Scotty.Action):

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of ‘setHeader’ (imported from Web.Scotty.Action):

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of ‘setHeader’ (imported from Web.Scotty.Action):

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of ‘setHeader’ (imported from Web.Scotty.Action):

Check warning on line 97 in Web/Scotty/Cookie.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of ‘setHeader’ (imported from Web.Scotty.Action):
{-# DEPRECATED setCookie "uses setHeader which is unsafe (#92). Please use setCookie1 instead"#-}

-- | Set a cookie, with full access to its options (see 'SetCookie')
--
-- NB : sanitizes the cookie value by keeping only the first characters before '\r' or '\n'
setCookie1 :: MonadIO m
=> SetCookie
-> ActionT m ()
setCookie1 = setCookieWith setHeader1

-- | Set a cookie, with full access to its options (see 'SetCookie')
setCookieWith :: MonadIO m
=> (Text -> Text -> ActionT m ())
-> SetCookie
-> ActionT m ()
setCookieWith f c = f "Set-Cookie"
$ decodeUtf8Lenient
$ BSL.toStrict
$ toLazyByteString
$ renderSetCookie c


-- | 'makeSimpleCookie' and 'setCookie' combined.
setSimpleCookie :: (MonadIO m)
=> Text -- ^ name
-> Text -- ^ value
-> ActionT m ()
setSimpleCookie n v = setCookie $ makeSimpleCookie n v
{-# DEPRECATED setSimpleCookie "uses setHeader which is unsafe (#92). Please use setSimpleCookie1 instead"#-}

-- | 'makeSimpleCookie' and 'setCookie1' combined.
--
-- NB : sanitizes the cookie value by keeping only the first characters before '\r' or '\n' (#92)
setSimpleCookie1 :: (MonadIO m)
=> Text -- ^ name
-> Text -- ^ value
-> ActionT m ()
setSimpleCookie1 n v = setCookie1 $ makeSimpleCookie n v

-- | Lookup one cookie name
getCookie :: (Monad m)
Expand Down
9 changes: 9 additions & 0 deletions Web/Scotty/Internal/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import Control.Monad.Trans.Class (MonadTrans(..))
import Control.Monad.Trans.Control (MonadBaseControl, MonadTransControl)

import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8 (splitWith)
import qualified Data.ByteString.Lazy.Char8 as LBS8 (ByteString)
import Data.Default.Class (Default, def)
import Data.Maybe (listToMaybe)
import Data.String (IsString(..))
import Data.Text (Text, pack)
import Data.Typeable (Typeable)
Expand Down Expand Up @@ -207,6 +209,13 @@ setContent c sr = sr { srContent = c }
setHeaderWith :: ([(HeaderName, BS.ByteString)] -> [(HeaderName, BS.ByteString)]) -> ScottyResponse -> ScottyResponse
setHeaderWith f sr = sr { srHeaders = f (srHeaders sr) }

-- | Take the first characters before either a Carrier Return ('\r') or Line Feed ('\n').
-- This can be used to sanitize headers.
splitAtCRLF :: BS.ByteString -> Maybe BS.ByteString
splitAtCRLF = listToMaybe . BS8.splitWith (\c -> c == '\n' ||
c == '\r'
)

setStatus :: Status -> ScottyResponse -> ScottyResponse
setStatus s sr = sr { srStatus = s }

Expand Down
7 changes: 6 additions & 1 deletion Web/Scotty/Trans.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ module Web.Scotty.Trans
, pathParams, captureParams, formParams, queryParams
, jsonData, files
-- ** Modifying the Response and Redirecting
, status, Lazy.addHeader, Lazy.setHeader, Lazy.redirect
-- *** Status
, status
-- *** Headers
, Lazy.addHeader, Lazy.setHeader
, Lazy.addHeader1, Lazy.setHeader1
, Lazy.redirect
-- ** Setting Response Body
--
-- | Note: only one of these should be present in any given route
Expand Down
13 changes: 13 additions & 0 deletions Web/Scotty/Trans/Lazy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
raise :: (MonadIO m) =>
T.Text -- ^ Error text
-> ActionT m a
raise = Base.raise . T.toStrict

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of ‘raise’ (imported from Web.Scotty.Action):

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of ‘raise’ (imported from Web.Scotty.Action):

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of ‘raise’ (imported from Web.Scotty.Action):

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of ‘raise’ (imported from Web.Scotty.Action):

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of ‘raise’ (imported from Web.Scotty.Action):

Check warning on line 19 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of ‘raise’ (imported from Web.Scotty.Action):
{-# DEPRECATED raise "Throw an exception instead" #-}

-- | Throw a 'StatusError' exception that has an associated HTTP error code and can be caught with 'rescue'.
--
-- Uncaught exceptions turn into HTTP responses corresponding to the given status.
raiseStatus :: Monad m => Status -> T.Text -> ActionT m a
raiseStatus s = Base.raiseStatus s . T.toStrict

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):

Check warning on line 26 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of ‘raiseStatus’ (imported from Web.Scotty.Action):
{-# DEPRECATED raiseStatus "Use status, text, and finish instead" #-}

-- | Redirect to given URL. Like throwing an uncatchable exception. Any code after the call to redirect
Expand All @@ -47,12 +47,25 @@

-- | Add to the response headers. Header names are case-insensitive.
addHeader :: MonadIO m => T.Text -> T.Text -> ActionT m ()
addHeader k v = Base.addHeader (T.toStrict k) (T.toStrict v)

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 50 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of ‘addHeader’ (imported from Web.Scotty.Action):
{-# DEPRECATED addHeader "does not validate header values which is potentially unsafe (#92). Please use addHeader1 instead"#-}

-- | Set one of the response headers. Will override any previously set value for that header.
-- Header names are case-insensitive.
setHeader :: MonadIO m => T.Text -> T.Text -> ActionT m ()
setHeader k v = Base.addHeader (T.toStrict k) (T.toStrict v)

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.3

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.0.2

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.2.8

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 8.10.7

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.4.6

In the use of ‘addHeader’ (imported from Web.Scotty.Action):

Check warning on line 56 in Web/Scotty/Trans/Lazy.hs

View workflow job for this annotation

GitHub Actions / ubuntu-latest / ghc 9.6.2

In the use of ‘addHeader’ (imported from Web.Scotty.Action):
{-# DEPRECATED setHeader "does not validate header values which is potentially unsafe (#92). Please use setHeader1 instead"#-}


-- | Add to the response headers. Header names are case-insensitive.
addHeader1 :: MonadIO m => T.Text -> T.Text -> ActionT m ()
addHeader1 k v = Base.addHeader1 (T.toStrict k) (T.toStrict v)

-- | Set one of the response headers. Will override any previously set value for that header.
-- Header names are case-insensitive.
setHeader1 :: MonadIO m => T.Text -> T.Text -> ActionT m ()
setHeader1 k v = Base.addHeader1 (T.toStrict k) (T.toStrict v)


text :: (MonadIO m) => T.Text -> ActionT m ()
text = Base.textLazy
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
* Deprecate `StatusError`, `raise` and `raiseStatus` (#351)
* Add doctest, refactor some inline examples into doctests (#353)
* document "`defaultHandler` only applies to endpoints defined after it" (#237)
* add `setHeader1`, `addHeader1`, deprecate `setHeader`, `addHeader` (#92)
* add `setCookie1`, `setSimpleCookie1` (#92)

Breaking:

* `setCookie` uses `setHeader` rather than `addHeader` (as it should)

## 0.20.1 [2023.10.03]

Expand Down
27 changes: 27 additions & 0 deletions test/Web/ScottySpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,33 @@ spec = do
it "stops the execution of an action" $ do
get "/scotty" `shouldRespondWith` 400

describe "setHeader" $ do
withApp (Scotty.get "/" $ setHeader "foo" "bar") $ do
it "sets a header" $ do
get "/" `shouldRespondWith` 200 {matchHeaders = ["foo" <:> "bar"]}
context "disregards CR and/or LF which could lead to security issues (#92)" $ do
withApp (Scotty.get "/" $ setHeader "X-Foo" "Hey\r\nContent-Type: bla") $ do
it "is vulnerable" $ do
get "/" `shouldRespondWith` 200 {
matchHeaders = [
"X-Foo" <:> "Hey\r\nContent-Type: bla"
]
}

describe "setHeader1" $ do
withApp (Scotty.get "/" $ setHeader1 "foo" "bar") $ do
it "sets a header" $ do
get "/" `shouldRespondWith` 200 {matchHeaders = ["foo" <:> "bar"]}
context "strips CR and/or LF from header values (#92)" $ do
withApp (Scotty.get "/" $ setHeader1 "X-Foo" "Hey\r\nContent-Type: bla") $ do
it "is not vulnerable" $ do
get "/" `shouldRespondWith` 200 {
matchHeaders = [
"X-Foo" <:> "Hey"
]
}


describe "setSimpleCookie" $ do
withApp (Scotty.get "/scotty" $ SC.setSimpleCookie "foo" "bar") $ do
it "responds with a Set-Cookie header" $ do
Expand Down
Loading