@@ -127,6 +127,47 @@ def test_dont_accept_relative_outside_of_root(self):
127127 # this is OK since the .. cancels out
128128 runtime ._lookup_template (ctx , "foo/../index.html" , index .uri )
129129
130+ def test_dont_accept_relative_outside_of_root_via_double_slash (self ):
131+ """test that double-slash URI prefix can't bypass the
132+ path traversal check"""
133+ with tempfile .TemporaryDirectory () as base :
134+ tmpl_dir = os .path .join (base , "app" , "templates" )
135+ os .makedirs (tmpl_dir )
136+ with open (os .path .join (tmpl_dir , "index.html" ), "w" ) as f :
137+ f .write ("Hello" )
138+
139+ secret = os .path .join (base , "secrets" , "creds.txt" )
140+ os .makedirs (os .path .dirname (secret ))
141+ with open (secret , "w" ) as f :
142+ f .write ("SECRET_KEY=supersecret123" )
143+
144+ tl = lookup .TemplateLookup (directories = [tmpl_dir ])
145+ rel = os .path .relpath (secret , tmpl_dir )
146+
147+ # single-slash prefix should also be blocked
148+ assert_raises_message (
149+ exceptions .TemplateLookupException ,
150+ "cannot be relative outside of the root path" ,
151+ tl .get_template ,
152+ "/" + rel ,
153+ )
154+
155+ # double-slash prefix must not bypass the check
156+ assert_raises_message (
157+ exceptions .TemplateLookupException ,
158+ "cannot be relative outside of the root path" ,
159+ tl .get_template ,
160+ "//" + rel ,
161+ )
162+
163+ # triple-slash prefix must not bypass the check
164+ assert_raises_message (
165+ exceptions .TemplateLookupException ,
166+ "cannot be relative outside of the root path" ,
167+ tl .get_template ,
168+ "///" + rel ,
169+ )
170+
130171 def test_checking_against_bad_filetype (self ):
131172 with tempfile .TemporaryDirectory () as tempdir :
132173 tl = lookup .TemplateLookup (directories = [tempdir ])
0 commit comments