This is an automated email from the ASF dual-hosted git repository.

juergbi pushed a commit to branch jbilleter/tar
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 66abd69982868dd51f57954b61ace9c5f0512597
Author: Jürg Billeter <[email protected]>
AuthorDate: Sat Aug 29 20:37:52 2026 +0200

    tests/sources/tar.py: Add symlink escape test
    
    Reported-by: Gjoko Krstic <[email protected]>
---
 tests/sources/tar.py | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/tests/sources/tar.py b/tests/sources/tar.py
index f169800ff..61631ff63 100644
--- a/tests/sources/tar.py
+++ b/tests/sources/tar.py
@@ -15,6 +15,7 @@
 # Pylint doesn't play well with fixtures and dependency injection from pytest
 # pylint: disable=redefined-outer-name
 
+import io
 import os
 from shutil import copyfile
 import subprocess
@@ -606,3 +607,34 @@ def test_symlinks(cli, tmpdir, datafiles):
 
     assert os.readlink(checkoutdir + "/absolute-symlink") == absolute_target
     assert os.readlink(checkoutdir + "/relative-symlink") == relative_target
+
+
[email protected](os.path.join(DATA_DIR, "symlinks"))
+def test_symlink_escape(cli, tmpdir, datafiles):
+    project = str(datafiles)
+    generate_project(project, config={"aliases": {"tmpdir": "file:///" + 
str(tmpdir)}})
+
+    os.mkdir(tmpdir / "OUTSIDE")
+
+    src_tar = tmpdir / "contents.tar.gz"
+    with tarfile.open(src_tar, "w:gz") as tar:
+        d = tarfile.TarInfo("contents")
+        d.type = tarfile.DIRTYPE
+        tar.addfile(d)
+
+        s = tarfile.TarInfo("contents/evil")
+        s.type = tarfile.SYMTYPE
+        s.linkname = str(tmpdir / "OUTSIDE")
+        tar.addfile(s)
+
+        f = tarfile.TarInfo("contents/evil/pwned")
+        data = b"pwned"
+        f.size = len(data)
+        tar.addfile(f, io.BytesIO(data))
+
+    result = cli.run(project=project, args=["source", "track", "target.bst"])
+    result.assert_success()
+    result = cli.run(project=project, args=["source", "fetch", "target.bst"])
+    result.assert_main_error(ErrorDomain.STREAM, None)
+    assert "would be extracted to" in result.stderr
+    assert "which is outside the destination" in result.stderr

Reply via email to