Skip to content

Fix symlink-following arbitrary file write in archive extraction#8303

Merged
lhoestq merged 1 commit into
huggingface:mainfrom
AAtomical:fix/extract-symlink-following
Jul 6, 2026
Merged

Fix symlink-following arbitrary file write in archive extraction#8303
lhoestq merged 1 commit into
huggingface:mainfrom
AAtomical:fix/extract-symlink-following

Conversation

@AAtomical

Copy link
Copy Markdown
Contributor

Extractor.extract() called shutil.rmtree(output_path, ignore_errors=True) before extracting. Since Python 3.8, shutil.rmtree() raises OSError on a symlink pointing to a directory, which ignore_errors=True silently swallows. An attacker with write access to a shared cache directory could pre-plant a symlink at the predictable extraction output path; rmtree would no-op on it, and extraction would then follow the symlink and write archive contents into the attacker-chosen target, yielding arbitrary file write as the victim.

The existing safemembers() zip-slip mitigation only validates member names and is blind to the output directory itself being a symlink.

Remove the symlink itself before extracting so contents can no longer be written through it.
#8296

Extractor.extract() called shutil.rmtree(output_path, ignore_errors=True)
before extracting. Since Python 3.8, shutil.rmtree() raises OSError on a
symlink pointing to a directory, which ignore_errors=True silently swallows.
An attacker with write access to a shared cache directory could pre-plant a
symlink at the predictable extraction output path; rmtree would no-op on it,
and extraction would then follow the symlink and write archive contents into
the attacker-chosen target, yielding arbitrary file write as the victim.

The existing safemembers() zip-slip mitigation only validates member names
and is blind to the output directory itself being a symlink.

Remove the symlink itself before extracting so contents can no longer be
written through it.
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@lhoestq lhoestq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm thx !

@lhoestq lhoestq merged commit ad2d853 into huggingface:main Jul 6, 2026
10 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants