MCPcopy
hub / github.com/tornadoweb/tornado / validate_absolute_path

Method validate_absolute_path

tornado/web.py:2956–3013  ·  view source on GitHub ↗

Validate and return the absolute path. ``root`` is the configured path for the `StaticFileHandler`, and ``path`` is the result of `get_absolute_path` This is an instance method called during request processing, so it may raise `HTTPError` or use methods like

(self, root: str, absolute_path: str)

Source from the content-addressed store, hash-verified

2954 return abspath
2955
2956 def validate_absolute_path(self, root: str, absolute_path: str) -> Optional[str]:
2957 """Validate and return the absolute path.
2958
2959 ``root`` is the configured path for the `StaticFileHandler`,
2960 and ``path`` is the result of `get_absolute_path`
2961
2962 This is an instance method called during request processing,
2963 so it may raise `HTTPError` or use methods like
2964 `RequestHandler.redirect` (return None after redirecting to
2965 halt further processing). This is where 404 errors for missing files
2966 are generated.
2967
2968 This method may modify the path before returning it, but note that
2969 any such modifications will not be understood by `make_static_url`.
2970
2971 In instance methods, this method's result is available as
2972 ``self.absolute_path``.
2973
2974 .. versionadded:: 3.1
2975 """
2976 # os.path.abspath strips a trailing /.
2977 # We must add it back to `root` so that we only match files
2978 # in a directory named `root` instead of files starting with
2979 # that prefix.
2980 root = os.path.abspath(root)
2981 if not root.endswith(os.path.sep):
2982 # abspath always removes a trailing slash, except when
2983 # root is '/'. This is an unusual case, but several projects
2984 # have independently discovered this technique to disable
2985 # Tornado's path validation and (hopefully) do their own,
2986 # so we need to support it.
2987 root += os.path.sep
2988 # The trailing slash also needs to be temporarily added back
2989 # the requested path so a request to root/ will match.
2990 if not (absolute_path + os.path.sep).startswith(root):
2991 raise HTTPError(403, "%s is not in root static directory", self.path)
2992 if os.path.isdir(absolute_path) and self.default_filename is not None:
2993 # need to look at the request.path here for when path is empty
2994 # but there is some prefix to the path that was already
2995 # trimmed by the routing
2996 if not self.request.path.endswith("/"):
2997 if self.request.path.startswith("//"):
2998 # A redirect with two initial slashes is a "protocol-relative" URL.
2999 # This means the next path segment is treated as a hostname instead
3000 # of a part of the path, making this effectively an open redirect.
3001 # Reject paths starting with two slashes to prevent this.
3002 # This is only reachable under certain configurations.
3003 raise HTTPError(
3004 403, "cannot redirect path with two initial slashes"
3005 )
3006 self.redirect(self.request.path + "/", permanent=True)
3007 return None
3008 absolute_path = os.path.join(absolute_path, self.default_filename)
3009 if not os.path.exists(absolute_path):
3010 raise HTTPError(404)
3011 if not os.path.isfile(absolute_path):
3012 raise HTTPError(403, "%s is not a file", self.path)
3013 return absolute_path

Callers 1

getMethod · 0.95

Calls 3

HTTPErrorClass · 0.85
redirectMethod · 0.80
joinMethod · 0.80

Tested by

no test coverage detected