Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate a filename in python

I'm writing a personal wiki-style program in Python that stores text files in a user configurable directory.

The program should be able to take a string (e.g. foo) from a user and create a filename of foo.txt. The user will only be able to create the file inside the wiki directory, and slashes will create a subdir (e.g. foo/bar becomes (path-to-wiki)/foo/bar.txt).

What is the best way to check that the input is as safe as possible? What do I need to watch out for? I know some common pitfalls are:

  • Directory traversal: ../
  • Null bytes: \0

I realize that taking user input for filenames is never 100% safe, but the program will only be run locally and I just want to guard for any common errors/glitches.

like image 287
Puzzled79 Avatar asked Dec 31 '11 07:12

Puzzled79


1 Answers

You can enforce the user to create a file/directory inside wiki by normalizing the path with os.path.normpath and then checking if the path begins with say '(path-to-wiki)'

os.path.normpath('(path-to-wiki)/foo/bar.txt').startswith('(path-to-wiki)')

To ensure that the user's entered path/filename doesn't contain anything nasty, you can force the user to enter a path or filename to either of Lower/Upper Alpha, Numeric Digits or may be hyphen or underscore.

Then you can always check the normalized filename using a similar regular expression

userpath=os.path.normpath('(path-to-wiki)/foo/bar.txt')
re.findall(r'[^A-Za-z0-9_\-\\]',userpath)

To summarize

if userpath=os.path.normpath('(path-to-wiki)/foo/bar.txt') then

if not os.path.normpath('(path-to-wiki)/foo/bar.txt').startswith('(path-to-wiki)')  
   or re.search(r'[^A-Za-z0-9_\-\\]',userpath):
  ... Do what ever you want with an invalid path
like image 100
Abhijit Avatar answered Sep 22 '22 22:09

Abhijit