@@ -36,6 +36,67 @@ func TestZipDirPreservesSymlinks(t *testing.T) {
3636 assert .Equal (t , "target.txt" , target )
3737}
3838
39+ func TestUnzipRejectsEscapingRelativeSymlink (t * testing.T ) {
40+ zipPath := filepath .Join (t .TempDir (), "escape-symlink.zip" )
41+ zipFile , err := os .Create (zipPath )
42+ require .NoError (t , err )
43+
44+ zipWriter := zip .NewWriter (zipFile )
45+ symlinkHeader := & zip.FileHeader {
46+ Name : "link.txt" ,
47+ Method : zip .Store ,
48+ }
49+ symlinkHeader .SetMode (os .ModeSymlink | 0777 )
50+ linkWriter , err := zipWriter .CreateHeader (symlinkHeader )
51+ require .NoError (t , err )
52+ _ , err = linkWriter .Write ([]byte (".." ))
53+ require .NoError (t , err )
54+ require .NoError (t , zipWriter .Close ())
55+ require .NoError (t , zipFile .Close ())
56+
57+ err = Unzip (zipPath , t .TempDir ())
58+ require .Error (t , err )
59+ assert .Contains (t , err .Error (), "illegal symlink target" )
60+ }
61+
62+ func TestUnzipSymlinkOverwritesExistingPath (t * testing.T ) {
63+ zipPath := filepath .Join (t .TempDir (), "overwrite-symlink.zip" )
64+ zipFile , err := os .Create (zipPath )
65+ require .NoError (t , err )
66+
67+ zipWriter := zip .NewWriter (zipFile )
68+ targetWriter , err := zipWriter .Create ("target.txt" )
69+ require .NoError (t , err )
70+ _ , err = targetWriter .Write ([]byte ("target contents" ))
71+ require .NoError (t , err )
72+
73+ symlinkHeader := & zip.FileHeader {
74+ Name : "link.txt" ,
75+ Method : zip .Store ,
76+ }
77+ symlinkHeader .SetMode (os .ModeSymlink | 0777 )
78+ linkWriter , err := zipWriter .CreateHeader (symlinkHeader )
79+ require .NoError (t , err )
80+ _ , err = linkWriter .Write ([]byte ("target.txt" ))
81+ require .NoError (t , err )
82+
83+ require .NoError (t , zipWriter .Close ())
84+ require .NoError (t , zipFile .Close ())
85+
86+ destDir := t .TempDir ()
87+ linkPath := filepath .Join (destDir , "link.txt" )
88+ require .NoError (t , os .WriteFile (linkPath , []byte ("old contents" ), 0644 ))
89+
90+ require .NoError (t , Unzip (zipPath , destDir ))
91+
92+ info , err := os .Lstat (linkPath )
93+ require .NoError (t , err )
94+ assert .True (t , info .Mode ()& os .ModeSymlink != 0 )
95+ target , err := os .Readlink (linkPath )
96+ require .NoError (t , err )
97+ assert .Equal (t , "target.txt" , target )
98+ }
99+
39100func TestUnzipFile (t * testing.T ) {
40101 // Create a temporary directory for test files
41102 sourceDir , err := os .MkdirTemp ("" , "zip-source-*" )
0 commit comments