spacecookie-1.1.0.0: test/Test/Sanitization.hs
{-# LANGUAGE QuasiQuotes #-}
module Test.Sanitization (sanitizationTests) where
import Network.Spacecookie.FileType (checkNoDotFiles, PathError (..))
import Network.Spacecookie.Path (sanitizePath, makeAbsolute)
import Control.Monad (forM_)
import System.OsPath.Posix (isAbsolute)
import System.OsString.Posix (pstr)
import Test.Tasty
import Test.Tasty.HUnit
sanitizationTests :: TestTree
sanitizationTests = testGroup "Sanitization of user input"
[ pathSanitization
, dotFileDetectionTest
, makeAbsoluteTest
]
pathSanitization :: TestTree
pathSanitization = testCase "sanitizePath behavior" $ do
let assertSanitize e p = assertEqual (show p) e $ sanitizePath p
assertSanitize [pstr|/root|] [pstr|/root|]
assertSanitize [pstr|/home/alice/.emacs.d/init.el|] [pstr|/home/alice/.emacs.d/init.el|]
assertSanitize [pstr|root|] [pstr|./root|]
assertSanitize [pstr|/tools/magrathea|] [pstr|//tools/magrathea|]
assertSanitize [pstr|/home/bob/Documents/important.txt|] [pstr|/home/bob//Documents/important.txt|]
assertSanitize [pstr|foo/bar/baz.txt|] [pstr|./foo/bar/./baz.txt|]
assertSanitize [pstr|/var/www/index..html|] [pstr|/var/www/.///index..html|]
assertSanitize [pstr|./|] [pstr|./.|]
assertSanitize [pstr|/|] [pstr|/.|]
assertSanitize [pstr|home/eve/|] [pstr|./home/./././eve////./.|]
assertSanitize [pstr|/home/bob/alice/private.txt|] [pstr|/home/bob/../alice/private.txt|]
dotFileDetectionTest :: TestTree
dotFileDetectionTest = testCase "spacecookie server detects dot files in paths" $ do
let assertDot p hasDot = forM_
[ (show p, p)
, (show p ++ " (sanitized)", sanitizePath p)
]
$ \(title, path) -> assertEqual title
(if hasDot then Left PathIsNotAllowed else Right ())
$ checkNoDotFiles path
assertDot [pstr|./normal/relative/path|] False
assertDot [pstr|.|] False
assertDot [pstr|/some/absolute/path|] False
assertDot [pstr|file.txt|] False
assertDot [pstr|/foo.html|] False
assertDot [pstr|./tmp/scratch.txt|] False
assertDot [pstr|./.|] False
assertDot [pstr|relative/./path|] False
assertDot [pstr|.emacs.d/init.el|] True
assertDot [pstr|.gophermap|] True
assertDot [pstr|/home/bob/.vimrc|] True
assertDot [pstr|/home/alice/.config/foot|] True
assertDot [pstr|./nixpkgs/.git/config|] True
-- only fail prior to sanitization
forM_
[ [pstr|dir/../traversal/../attack|], [pstr|../../../actual/traversal|] ]
$ \p -> do
assertEqual (show p) (Left PathIsNotAllowed) $ checkNoDotFiles p
assertEqual (show p) (Right ()) $ checkNoDotFiles (sanitizePath p)
makeAbsoluteTest :: TestTree
makeAbsoluteTest = testCase "relative paths are correctly converted to absolute ones" $ do
let assertAbsolute expected given = do
assertEqual (show given) expected $ makeAbsolute given
assertBool ("makeAbsolute " ++ show given ++ " is absolute")
$ isAbsolute (makeAbsolute given)
assertAbsolute [pstr|/foo/bar|] [pstr|/foo/bar|]
assertAbsolute [pstr|/foo/bar|] [pstr|./foo/bar|]
assertAbsolute [pstr|/foo/bar|] [pstr|foo/bar|]
assertAbsolute [pstr|/|] [pstr|.|]
assertAbsolute [pstr|/|] [pstr|./|]
assertAbsolute [pstr|/bar/foo|] [pstr|././bar/foo|]
assertAbsolute [pstr|/../bar/foo|] [pstr|./../bar/foo|]
assertAbsolute [pstr|/../bar/foo|] [pstr|../bar/foo|]