Fix the path resolver behind a download route

Review the AI's codeMedium15 min

Your task

An AI wrote a download route that joined req.params.name onto /srv/uploads and sent the file. A name like ../../etc/passwd, or an encoded form of it, could read any file on the server. The fix resolves the name itself and refuses anything that leaves the uploads folder. The service also runs on Windows hosts, where \ separates folders just as / does.

An assistant wrote resolve_upload_path(base_dir, requested_name). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • base_dir: the uploads folder, such as "/srv/uploads".
  • requested_name: the raw name from the URL. It may be percent-encoded, where %2e stands for . and %2f for /.
  • Return the resolved path, or "" to refuse the request.

Rules the tests check:

  • Remove every trailing / and \ from base_dir. If nothing is left, refuse.
  • Percent-decode the name exactly once: each % followed by two hex digits whose value is 127 or less becomes that character. Everything else stays as it is. Do not decode the result a second time.
  • Refuse if the decoded name is empty, contains a NUL character (code 0), or starts with / or \.
  • Split the decoded name into segments at every / and every \. Skip empty segments and . segments. A .. segment removes the last kept segment. If there is none to remove, refuse.
  • If no segments are kept, refuse.
  • Otherwise return the base, then each kept segment with a / in front of it.

Examples

resolve_upload_path(base_dir: str, requested_name: str) -> str
Example 1
Inputresolve_upload_path("/srv/uploads", "notes.txt")
Output"/srv/uploads/notes.txt"
Example 2
Inputresolve_upload_path("/srv/uploads", "../../etc/passwd")
Output""
Example 3
Inputresolve_upload_path("/srv/uploads", "%2e%2e%2fetc%2fpasswd")
Output""