GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-57911: Sanitize symlink targets in tarfile on win32 by wiomoc · Pull Request #138309 · python/cpython

Conversation

@wiomoc

@wiomoc wiomoc commented Aug 31, 2025 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

CC @encukou

  • Issue: relative symlinks in tarfile.extract broken (windows) #57911

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@wiomoc
pythongh-57911: Sanitize symlink targets in tarfile on win32
382e7c4
@bedevere-app bedevere-app Bot mentioned this pull request Aug 31, 2025
relative symlinks in tarfile.extract broken (windows) #57911
Closed
@wiomoc
wiomoc force-pushed the fix-tar-extract-symlink-win32-path branch from fac592d to 5956b5d Compare August 31, 2025 23:07
@wiomoc
fix test as dotdot resolves early on win32
2ccc462
@wiomoc
wiomoc force-pushed the fix-tar-extract-symlink-win32-path branch from 5956b5d to 2ccc462 Compare August 31, 2025 23:08
@wiomoc
wiomoc marked this pull request as ready for review August 31, 2025 23:34
@wiomoc
wiomoc requested a review from ethanfurman as a code owner August 31, 2025 23:34
@bedevere-app bedevere-app Bot added the awaiting review label Aug 31, 2025
@encukou

encukou commented Sep 1, 2025

Copy link
Copy Markdown
Member

Should this be done for hardlinks as well?

I'd prefer saying “rewrite” rather than “sanitize”, as this is not fixing unsafe input.

We should probably skip this for leading // -- that would turn symlink targets into UNC paths, where I'm not sure of the security implications, and anyway it's not something you'd find in a portable UNIX-based tarball.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@wiomoc

wiomoc commented Sep 1, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Should this be done for hardlinks as well?

This problem doesn't seam to occur when creating hardlinks:

>>> os.mkdir("tmp")
>>> os.mkdir("tmp\\child")
>>> open("tmp\\child\\test.txt", "w").write("hello world")
11
>>> os.link("tmp/child/test.txt", "tmp/testlink.txt")
>>> open("tmp\\testlink.txt").read()
'hello world'

We should probably skip this for leading // -- that would turn symlink targets into UNC paths, where I'm not sure of the security implications, and anyway it's not something you'd find in a portable UNIX-based tarball.

On the one hand, I see the risk of security implications, but I also note that in pathlib, slashes are also replaced in UNC paths.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@wiomoc
adjust wording
58f5c2b
encukou
encukou reviewed Sep 2, 2025
View reviewed changes

@encukou encukou left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK; re-reading the duscussion I see experts suggesting to always replace, so let's go with that.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/test/test_tarfile.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@wiomoc
default dotdot_resolves_early=True
942b6e3
@wiomoc
wiomoc requested a review from encukou September 2, 2025 20:43
@encukou encukou added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 3, 2025
@bedevere-bot

bedevere-bot commented Sep 3, 2025

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @encukou for commit 942b6e3 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F138309%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 3, 2025
encukou
encukou reviewed Sep 3, 2025
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2025-08-31-22-10-22.gh-issue-57911.N_Ixtv.rst Outdated
Comment on lines +1 to +2
When extracting tar files on Windows Posix flavoured path separators in symlink
targets will be replaced by backward-slashes to prevent corrupted links.

@encukou encukou Sep 3, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When extracting tar files on Windows Posix flavoured path separators in symlink
targets will be replaced by backward-slashes to prevent corrupted links.
When extracting tar files on Windows, slashes in symlink
targets will be replaced by backslashes to prevent corrupted links.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

wiomoc reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@encukou

encukou commented Sep 3, 2025

Copy link
Copy Markdown
Member

Looks good! Could you also add an entry to Doc/whatsnew/3.15.rst?

wiomoc reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

wiomoc added 2 commits September 3, 2025 17:29
@wiomoc
Merge branch 'main' into fix-tar-extract-symlink-win32-path
eda70ae
@wiomoc
add whatsnew entry
c04488a
@wiomoc
wiomoc requested a review from AA-Turner as a code owner September 3, 2025 15:39
@encukou
encukou merged commit c1a9c23 into python:main Sep 5, 2025
@bedevere-app bedevere-app Bot removed the awaiting review label Sep 5, 2025
@encukou

encukou commented Sep 5, 2025

Copy link
Copy Markdown
Member

Thank you!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz

picnixz commented Sep 7, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

I think this broke some buildbots: https://buildbot.python.org/#/builders/914. It wasn't detected until #138276 (which was 20h ago, but this change is 2 days ago and the previous buildbot run was 3 days ago)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@AA-Turner

AA-Turner commented Sep 7, 2025

Copy link
Copy Markdown
Member

@picnixz if you open a revert PR as draft, you could use !buildbot to check this worker & see if it passes again?

A

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz

picnixz commented Sep 7, 2025

Copy link
Copy Markdown
Member

I'm not on a dev session but I'll do it tomorrow if no one beats me to it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@wiomoc

wiomoc commented Sep 7, 2025

Copy link
Copy Markdown
Contributor Author

The test only fails, when running on a Windows system with disabled symlink support - therefore it didn't occure on GH actions.
I have a possible fix in #138626

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

lkollar pushed a commit to lkollar/cpython that referenced this pull request Sep 9, 2025
@wiomoc @lkollar
pythongh-57911: Sanitize symlink targets in tarfile on win32 (pythonG…
356a0ff
…H-138309)
@dnicolodi dnicolodi mentioned this pull request Jun 18, 2026
tarfile.TarFile.add() does not normalize symlink targets on Windows #151669
Closed
@dnicolodi

dnicolodi commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Shouldn't the inverse normalization of path separator characters be done in tarfile.TarFile.add()? Otherwise, the symlink targets written in the tar archive are wrong when extracted on another platform (and I believe not conforming to the standard). See #151669.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dnicolodi dnicolodi mentioned this pull request Jun 18, 2026
gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() #151671
Merged
@encukou

encukou commented Jun 19, 2026

Copy link
Copy Markdown
Member

I believe not conforming to the standard

Which standard are you referring to?

Shouldn't the inverse normalization of path separator characters be done in tarfile.TarFile.add()?

Perhaps, but, I'm still fixing issues from the last time I changed long-standing behaviour in tarfile.
The change needs far stronger justification than I can see currently.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dnicolodi

dnicolodi commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Which standard are you referring to?

The tar format definition. I haven't checked the format definition (and I don't even know whether it exists), but all paths in a tar file are usually stored with / as the path separator (and this is what the tarfile module implements, with one exception). The current behavior of tarfile.TarFile.add() is to use native path separators for symlink targets. On Windows, this result in tar files that produce wrong symbolic links when extracted on POSIX platforms.

Perhaps, but, I'm still fixing issues from the last time I changed long-standing behaviour in tarfile.

Think to this as more fallout from these changes. The normalization has always been missing, but it broke my application only since this PR has been merged (and Windows support for symlinks is more widespread: I would not have noticed it if not for the fact that GitHub Actions Windows runners have support for symlink enabled).

The change needs far stronger justification than I can see currently.

tar archives produced by code like

os.symlink("../baz", "foo")
tar = tarfile.open("sample.tar", "w")
tar.add("foo")
tar.close()

are currently invalid when created on Windows. In other words, they produce the wrong filesystem objects when extracted on a platform that uses / as path separator.

Maybe code like this can be fixed specifying a filter function that fixes the path separators on Windows. However, the exact same argument could have been made for the change in this PR. On the other hand, I don't see a way to fix tar archives produced by shutil.make_archive().

I think that having the normalization only on extract is the worst possible outcome as it introduces unnecessary asymmetry: users of the tarfile module need special treatment of symlinks on Windows when creating archives, but not when extracting them.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dnicolodi dnicolodi mentioned this pull request Jun 19, 2026
meson dist results in invalid tar archives on Windows when the repository contains symlinks mesonbuild/meson#15932
Closed
@encukou

encukou commented Jun 19, 2026

Copy link
Copy Markdown
Member

Which standard are you referring to?
The tar format definition. I haven't checked the format definition (and I don't even know whether it exists)

Could you check, then? An actual reference to the standard would make this an easy sell -- that would mean that relevant people already thought about this.
Talking about imaginary standards, on the other hand, make me think I need to consult a tarfile expert on this -- or become one (i.e. find all the caveats and consequences myself).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bonzini

bonzini commented Jun 19, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

The tar standard is a POSIX standard. POSIX does not make backslashes special in any way; they are a valid character in a file name. Therefore, POSIX treats a link name of a\b as a symbolic link to the file a\b in the current directory.

For example, https://man.freebsd.org/cgi/man.cgi?query=tar&apropos=0&sektion=5&manpath=FreeBSD+7.0-RELEASE&arch=default&format=html has

       linkpath
	       The full path of the linked-to file.  Note that this is encoded
	       in UTF8 and can thus include non-ASCII characters.

and https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271 defines

3.170 Filename

A sequence of bytes consisting of 1 to {NAME_MAX} bytes used to name a file. The bytes composing the name shall not contain the <NUL> or <slash> characters. In the context of a pathname, each filename shall be followed by a <slash> or a <NUL> character; elsewhere, a filename followed by a <NUL> character forms a string (but not necessarily a character string). The filenames dot and dot-dot have special meaning. A filename is sometimes referred to as a "pathname component". See also Pathname.

3.271 Pathname

A string that is used to identify a file. In the context of POSIX.1-2017, a pathname may be limited to {PATH_MAX} bytes, including the terminating null byte. It has optional beginning <slash> characters, followed by zero or more filenames separated by <slash> characters. A pathname can optionally contain one or more trailing <slash> characters. Multiple successive <slash> characters are considered to be the same as one <slash>, except for the case of exactly two leading <slash> characters.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bonzini

bonzini commented Jun 19, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Found something in the POSIX standard as well (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06), where directory entry type 2 "represents a symbolic link. The contents of the symbolic link shall be stored in the linkname field."

Within tar files, the contents of the symbolic link are best described in the linkpath extension record, which is defined as follows: "The pathname of a link being created to another file, of any type, previously archived. This record shall override the linkname field in the following ustar header block(s)."

In other words, the target of a symbolic link in a tar file should indeed be a pathname, and as such separated by forward slashes.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dnicolodi

dnicolodi commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Thanks @bonzini !

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dnicolodi

dnicolodi commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

@encukou I find the specification quotes by @bonzini clear in this respect. What is the best way to move this forward? I would love to see fix for this problem included in Python 3.15, if possible. That would avoid having to carry a downstream workaround for the issue we encountered testing with Python 3.15b2.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rgommers

rgommers commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Perhaps, but, I'm still fixing issues from the last time I changed long-standing behaviour in tarfile.
The change needs far stronger justification than I can see currently.

Since no one said it explicitly yet: this introduces a regression for sdist creation with meson-python on Windows under Python 3.15. It's likely that that also affects other build backends that rely on git archive + tarfile. That's about as strong a justification as one would need I think?

The regression is fixed by gh-151671, which looks correct.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bonzini

bonzini commented Jun 27, 2026

Copy link
Copy Markdown

If this is not fixed, I guess meson would have to vendor the tarfile module. 🤷

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eli-schwartz

eli-schwartz commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

If this is not fixed, I guess meson would have to vendor the tarfile module. 🤷

We will not, so don't bother suggesting it again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou

encukou commented Jun 29, 2026

Copy link
Copy Markdown
Member

Thanks for the standard links. I'm... not sure if I'd call any of them “the” tar standard; it looks like it's best to not talk about standards in this issue.


this introduces a regression for sdist creation with meson-python on Windows under Python 3.15.

I see: mesonbuild/meson#15932
It's about extracting to the filesystem, and then re-packing into a tarfile.
That looks like a reasonable use case. It can introduce FS-related artifacts (like normalization), but it'll also give you a more surprise-free tarball.


So, we have a regression. That gives us two options:

  • Revert this (a fix for a 2012 issue), and try again in 3.16. That's the default course of action in beta.
  • Apply gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() #151671 (replace backslashes with slashes when creating the archive). This is a new feature. I now think that's the right way to go, but of course it might have unintended consequences, again.

@hugovk, do you think we should add the feature to 3.15?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk

hugovk commented Jul 3, 2026

Copy link
Copy Markdown
Member

Let's try #151671 for 3.15. We can still revert during the beta, if more issues come up, and also during the RC.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

encukou pushed a commit that referenced this pull request Jul 10, 2026
@dnicolodi
gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() (G…
cc31641
…H-151671)

This applies a normalization when creating members vrom the filesystem,
 complementary to the one added to tarfile.TarFile.extract() in gh-138309
that does it in the other direction.
This solves an issue with round-tripping through the filesystem.
@miss-islington miss-islington mentioned this pull request Jul 10, 2026
[3.15] gh-151669: Normalize symlink targets in tarfile.TarFile.gettarinfo() (GH-151671) #153517
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@encukou encukou encukou left review comments
@ethanfurman ethanfurman Awaiting requested review from ethanfurman ethanfurman is a code owner
@AA-Turner AA-Turner Awaiting requested review from AA-Turner AA-Turner is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

10 participants

@wiomoc @encukou @bedevere-bot @picnixz @AA-Turner @dnicolodi @bonzini @rgommers @eli-schwartz @hugovk
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.