@@ -33,8 +33,28 @@ def _add_field_value(self, field_name: str, value: Union[str, bytes]) -> None:
33
33
else :
34
34
self ._storage [field_name ].append (value )
35
35
36
- def get (self , field_name : str , default : Any = None ) -> Union [str , bytes , None ]:
36
+ @staticmethod
37
+ def _encode_html_entities (value ):
38
+ """Encodes unsafe HTML characters."""
39
+ return (
40
+ str (value )
41
+ .replace ("&" , "&" )
42
+ .replace ("<" , "<" )
43
+ .replace (">" , ">" )
44
+ .replace ('"' , """ )
45
+ .replace ("'" , "'" )
46
+ )
47
+
48
+ def get (
49
+ self , field_name : str , default : Any = None , * , safe = True
50
+ ) -> Union [str , bytes , None ]:
37
51
"""Get the value of a field."""
52
+ if safe :
53
+ return self ._encode_html_entities (
54
+ self ._storage .get (field_name , [default ])[0 ]
55
+ )
56
+
57
+ _debug_warning_nonencoded_output ()
38
58
return self ._storage .get (field_name , [default ])[0 ]
39
59
40
60
def get_list (self , field_name : str ) -> List [Union [str , bytes ]]:
@@ -348,3 +368,12 @@ def _parse_headers(header_bytes: bytes) -> Headers:
348
368
for name , value in [header_line .split (": " , 1 )]
349
369
}
350
370
)
371
+
372
+
373
+ def _debug_warning_nonencoded_output ():
374
+ """Warns about XSS risks."""
375
+ print (
376
+ "WARNING: Setting safe to False makes XSS vulnerabilities possible by "
377
+ "allowing access to raw untrusted values submitted by users. If this data is reflected "
378
+ "or shown within HTML without proper encoding it could enable Cross-Site Scripting."
379
+ )
0 commit comments