MCPcopy
hub / github.com/pallets/werkzeug / safe_join

Function safe_join

src/werkzeug/security.py:145–201  ·  src/werkzeug/security.py::safe_join

Safely join zero or more untrusted path components to a trusted base directory to avoid escaping the base directory. The untrusted path is assumed to be from/for a URL, such as for serving files. Therefore, it should only use the forward slash ``/`` path separator, and will be joine

(directory: str, *untrusted: str)

Source from the content-addressed store, hash-verified

143
144
145def safe_join(directory: str, *untrusted: str) -> str | None:
146 class="st">"""Safely join zero or more untrusted path components to a trusted base
147 directory to avoid escaping the base directory.
148
149 The untrusted path is assumed to be from/for a URL, such as for serving
150 files. Therefore, it should only use the forward slash ``/`` path separator,
151 and will be joined using that separator. On Windows, the backslash ``\\``
152 separator is not allowed.
153
154 :param directory: The trusted base directory.
155 :param untrusted: The untrusted path components relative to the
156 base directory.
157 :return: A safe path, otherwise ``None``.
158
159 .. versionchanged:: 3.1.6
160 Special device names in multi-segment paths are not allowed on Windows.
161
162 .. versionchanged:: 3.1.5
163 More special device names, regardless of extension or trailing spaces,
164 are not allowed on Windows.
165
166 .. versionchanged:: 3.1.4
167 Special device names are not allowed on Windows.
168 class="st">"""
169 if not directory:
170 class="cm"># Ensure we end up with ./path if directory=class="st">"" is given,
171 class="cm"># otherwise the first untrusted part could become trusted.
172 directory = class="st">"."
173
174 parts = [directory]
175
176 for part in untrusted:
177 if not part:
178 continue
179
180 part = posixpath.normpath(part)
181
182 if (
183 os.path.isabs(part)
184 class="cm"># ntpath.isabs doesn't catch this
185 or part.startswith(class="st">"/")
186 or part == class="st">".."
187 or part.startswith(class="st">"../")
188 or any(sep in part for sep in _os_alt_seps)
189 or (
190 os.name == class="st">"nt"
191 and any(
192 p.partition(class="st">".")[0].strip().upper() in _windows_device_files
193 for p in part.split(class="st">"/")
194 )
195 )
196 ):
197 return None
198
199 parts.append(part)
200
201 return posixpath.join(*parts)

Callers 7

test_safe_joinFunction · 0.90
test_safe_join_os_sepFunction · 0.90
send_from_directoryFunction · 0.85
loaderMethod · 0.85

Calls 1

appendMethod · 0.80

Tested by 5

test_safe_joinFunction · 0.72
test_safe_join_os_sepFunction · 0.72