addurl --preserve-filename and a few related changes
* addurl --preserve-filename: New option, uses server-provided filename without any sanitization, but with some security checking. Not yet implemented for remotes other than the web. * addurl, importfeed: Avoid adding filenames with leading '.', instead it will be replaced with '_'. This might be considered a security fix, but a CVE seems unwattanted. It was possible for addurl to create a dotfile, which could change behavior of some program. It was also possible for a web server to say the file name was ".git" or "foo/.git". That would not overrwrite the .git directory, but would cause addurl to fail; of course git won't add "foo/.git". sanitizeFilePath is too opinionated to remain in Utility, so moved it. The changes to mkSafeFilePath are because it used sanitizeFilePath. In particular: isDrive will never succeed, because "c:" gets munged to "c_" ".." gets sanitized now ".git" gets sanitized now It will never be null, because sanitizeFilePath keeps the length the same, and splitDirectories never returns a null path. Also, on the off chance a web server suggests a filename of "", ignore that, rather than trying to save to such a filename, which would fail in some way.
This commit is contained in:
parent
54599207f7
commit
6952060665
9 changed files with 132 additions and 39 deletions
56
Annex/UntrustedFilePath.hs
Normal file
56
Annex/UntrustedFilePath.hs
Normal file
|
@ -0,0 +1,56 @@
|
|||
{- handling untrusted filepaths
|
||||
-
|
||||
- Copyright 2010-2020 Joey Hess <id@joeyh.name>
|
||||
-
|
||||
- Licensed under the GNU AGPL version 3 or higher.
|
||||
-}
|
||||
|
||||
module Annex.UntrustedFilePath where
|
||||
|
||||
import Data.Char
|
||||
import System.FilePath
|
||||
|
||||
{- Given a string that we'd like to use as the basis for FilePath, but that
|
||||
- was provided by a third party and is not to be trusted, returns the closest
|
||||
- sane FilePath.
|
||||
-
|
||||
- All spaces and punctuation and other wacky stuff are replaced
|
||||
- with '_', except for '.'
|
||||
-
|
||||
- "../" becomes ".._", which is safe.
|
||||
- "/foo" becomes "_foo", which is safe.
|
||||
- "c:foo" becomes "c_foo", which is safe even on windows.
|
||||
-
|
||||
- Leading '.' is also replaced with '_', so ".git/foo" becomes "_git_foo"
|
||||
- and so no dotfiles that might control a program are inadvertently created.
|
||||
-}
|
||||
sanitizeFilePath :: String -> FilePath
|
||||
sanitizeFilePath = leadingdot . map sanitize
|
||||
where
|
||||
sanitize c
|
||||
| c == '.' = c
|
||||
| isSpace c || isPunctuation c || isSymbol c || isControl c || c == '/' = '_'
|
||||
| otherwise = c
|
||||
|
||||
leadingdot ('.':s) = '_':s
|
||||
leadingdot s = s
|
||||
|
||||
escapeSequenceInFilePath :: FilePath -> Bool
|
||||
escapeSequenceInFilePath f = '\ESC' `elem` f
|
||||
|
||||
{- ../ is a path traversal, no matter where it appears.
|
||||
-
|
||||
- An absolute path is, of course.
|
||||
-}
|
||||
pathTraversalInFilePath :: FilePath -> Bool
|
||||
pathTraversalInFilePath f
|
||||
| isAbsolute f = True
|
||||
| any (== "..") (splitPath f) = True
|
||||
-- On windows, C:foo with no directory is not considered absolute
|
||||
| hasDrive f = True
|
||||
| otherwise = False
|
||||
|
||||
gitDirectoryInFilePath :: FilePath -> Bool
|
||||
gitDirectoryInFilePath = any (== ".git")
|
||||
. map dropTrailingPathSeparator
|
||||
. splitPath
|
Loading…
Add table
Add a link
Reference in a new issue