php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69536 Extracted ZipArchive archives have insecure permissions when extracted by OSX
Submitted: 2015-04-27 16:13 UTC Modified: 2020-03-29 04:22 UTC
Votes:5
Avg. Score:4.2 ± 0.7
Reproduced:5 of 5 (100.0%)
Same Version:3 (60.0%)
Same OS:4 (80.0%)
From: kevin dot cupp at ellislab dot com Assigned:
Status: No Feedback Package: Zip Related
PHP Version: 5.5.24 OS: OSX
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: kevin dot cupp at ellislab dot com
New email:
PHP Version: OS:

 

 [2015-04-27 16:13 UTC] kevin dot cupp at ellislab dot com
Description:
------------
In PHP 5.5 and above, ZipArchive is creating archives that, when extracted by OSX, have its folders permissions set to 777 and files set to 666. In PHP 5.4, everything defaults to 755. When using a third-party extractor, such as The Unarchiver for OSX, permissions are normal, so it is only a problem (to my knowledge) with OSX's native unarchiver.

It could be argued that since it's a problem with OSX's unarchiver, the ball is in their court. But since it works fine on archives created in <= 5.4, I'm wondering if something could be done on PHP's end to write its zips in a way that OSX's unarchiver will not misinterpret, as a lot of folks are creating zips with PHP and a lot of customers are extracting those zips on their Macs. I'm not expecting original permissions be retained, just that ZipArchive writes its archives in a way that allows OSX pick a more sane default again, like 755.

Test script:
---------------
$zip = new ZipArchive();
$zip->open('./test.zip', ZIPARCHIVE::CREATE);
$zip->addEmptyDir('archive');
$zip->addFile('./test.php', 'archive/test.php');
$zip->close();

Expected result:
----------------
I expect an archive to be created, that when extracted with OSX's native unarchiver, the files have a relatively secure default permission applied to them, as in PHP 5.4.

Actual result:
--------------
Extracted files have a permission of 666, folders are 777.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-04-29 20:37 UTC] cmb@php.net
A slight variation of the supplied test script to make the issue
more easily reproducible:

    $zip = new ZipArchive();
    $zip->open('69536.zip',ZipArchive::CREATE);
    $zip->addFromString('foo','bar');
    $zip->close();

Recent versions of PHP set the "version made by" (byte no.
0x2A-0x2B in the archives generated by the test script) to 0x1403,
whereas former PHP versions used 0x1400. 0x14 is the ZIP version,
0x00 means DOS, 0x03 means Unix. I suppose that's what makes the
difference for OS X's native unarchiver.
 [2015-05-05 14:57 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2015-05-05 14:57 UTC] cmb@php.net
Just found the relevant entry in the changelog of libzip 0.11.2:

| For newly added files, set operating system to UNIX, permissions
| to 0666 (0777 for directories).
 [2018-11-23 08:40 UTC] peter dot achutha at gmail dot com
I am seeing this problem, ZipArchieve not working properly, in PHP versions 

7.3.0RC1	
7.2.10		
7.1.22		
7.0.32		
5.6.38		

ZipArchive is changing file permissions. All zipped files when unzipped have files permissions set to 0666 and directories set to 0777. The extracted PHP scripts cannot be executed. On some website I get "Error 500 - Internal Server Error" on others it is a similar message. When I change the permission to 0644 the PHP scripts run correctly.

Test Script
------------------
$zipArchive = new ZipArchive();
echo '<br>Destination ZIP: '.$zip_name.' <br>';
$return = $zipArchive->open($zip_name, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE );

if(  $return === TRUE)
	{
	//you can change the file names to what ever file you want to include in the zip
	$zipArchive->addFile('testmail.php', 'testmail.php');
	$zipArchive->addFile('testsendemail.php', 'testsendemail.php');
	$zipArchive->addFile('tmpX.txt', 'tmpX.txt');	
	$zipArchive->addFile('xmyreqdb.txt', 'xmyreqdb.txt');	
	} else {
	echo '<br>Failed Archive: '.$return;
	$stopemail = 'STOP';
	}
$ret = $zipArchive->close();
------------------

ZipArchive works for PHP versions:-
5.5.38		
5.4.45		
5.3.29		


So for now I cannot upgrade my site to a version of PHP higher than 5.5 because my zipped up PHP scripts, using a higher version of PHP, sent to customers fail to work when unzipped at their site. Suspect this is because the zip function sets the permission of the files being zipped to 0666 and directories to 0777 instead of copying the original permissions.

Please help fix this as soon as possible.
 [2019-02-22 08:16 UTC] peter dot achutha at gmail dot com
I ran another test on the PHP zip archive issue. I found that, with PHP 5.5 all file permissions are set to 0644. It does not matter whether the original file permissions were set to 0666 or 0444 or any other value. When you unzip the file the the permissions will be set to 0644.

I then tested this with PHP 5.6 and tried to zip and unzip files whose permissions were 0644 or 0444. When unzipped their permissions where set to 0666.

Further testing showed that the file permissions were set at the point of compression and not during unzipping. As I unzipped a file under PHP 5.6, that was zipped under PHP 5.5, and it unzipped with file permission of 0644. When I unzipped a file under PHP 5.5 that was zipped under PHP 5.6 the file permission were set to 0666. It did not matter what the original permissions were.

This clearly shows that the PHP zip archive function does not check the file or directory permissions when zipping files. It just defaults them to 0644 or 0666. Why?

Why did the developers not check the file permissions for the files being compressed and use those values? fileperms()? Can't we specify what permission we want the directories and files to be? For example:-

$zipArchive->addFile('atestzip.php', 'atestzip.php', 0644);

By doing this, we can write a PHP script to check every file's permission and set the permission before adding it to be compressed. If the permission is not set then a default setting can be used.
 [2019-02-23 01:03 UTC] peter dot achutha at gmail dot com
I have written about this on my blog, http://drpetersnews.com/php-zip-archive-not-working-apache-server-hard-disk-full-problems.php, as I really like using zip. 

I do hope the authorities will restore PHP zip archives to work with all versions of PHP, from 5.5 to 7.3.
 [2019-07-09 02:04 UTC] peter dot achutha at gmail dot com
I compressed my website today with 3 different compression methods are below are the results:-

drpeterscode-20190709-0944.tar		Tar Archive		491.18MB 100.00%
drpeterscode-20190709-0944.tar.gz	GZiped Tar Archive	358.05MB  72.89%
drpeterscode-20190709-0944.zip		Zip Archive		367.13MB  74.74%

It looks like zip archives are very good compared to Tar archives. The Zip archive was only 2.47% bigger than the GZipped Tar Archive which is a negligible amount.

Furthermore, I ran gtmetrix.com test on the speed of my webpages under PHP 7.3 and PHP 5.5 and there was no difference in speed.

Please upgrade zip archives so that it will work correctly in all versions of PHP from 5.5 to 7.3.
 [2019-07-09 02:06 UTC] requinix@php.net
> It looks like zip archives are very good compared to Tar archives.
Probably related to how TARs are uncompressed.
 [2020-03-18 13:00 UTC] remi@php.net
-Status: Verified +Status: Feedback
 [2020-03-18 13:00 UTC] remi@php.net
this is not a PHP/zip issue, rather a libzip one.

ZIP format is inherited from the old MS-DOS time and thus don't really manage permissions.

Some stuff is possible using the external attributes, but this is OS dependant, and raise portability issues.

extractTo document have been amended to raise user attention about umask usage.

setExternalAttributesName documentation has an example how to save permissions
getExternalAttributesIndex documentation has an example how to restore permissions.
 [2020-03-29 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 19:01:29 2024 UTC