Skip to content

--output-dir can be escaped by glob-referenced output filenames (-o "#1") #23067

Description

@bupt-Yy-young

Environment: curl 8.22.0 on Linux (also reproduced on current master). CLI tool only.

What happens

--output-dir is supposed to keep all downloads inside the given directory, but if the output
filename comes from a URL glob via -o "#N" (or #<name>), the substituted glob match is used
as-is and can walk out of the directory.

Repro

Serve anything on http://127.0.0.1:8080/, then:

$ mkdir -p work/out && cd work
$ curl --output-dir out -o "#1" "http://127.0.0.1:8080/files/{a,../escaped}"
$ ls out
a
$ ls -l escaped        # created in work/, outside out/

The glob produces http://127.0.0.1:8080/files/a and .../files/../escaped; for the second one the
#1 reference substitutes the raw match ../escaped and the file ends up at out/../escaped.

Why

  • setup_outfile() just concatenates: curl_maprintf("%s/%s", output_dir, per->outfile).
  • glob_match_url() substitutes the raw glob match into the output name; on non-Windows there is no
    sanitization of / or .. (only _WIN32/MSDOS builds sanitize, with SANITIZE_ALLOW_PATH anyway).
  • -O is fine because the name comes from the last URL path segment and the URL API normalizes /dir/...

Expected vs actual

Expected: files stay inside --output-dir. Actual: file written outside it (path-isolation /
file-integrity issue). Relevant when the URL/glob comes from untrusted input combined with
--output-dir + -o "#N".

A fix could reject or neutralize / and .. in glob-referenced output names, like -O is limited to
a single path component.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions