[wp-trac] [WordPress Trac] #65320: WordPress 7 core update silently truncates filenames longer than 100 characters during extraction (wp-includes/php-ai-client/ affected)

WordPress Trac noreply at wordpress.org
Fri May 22 09:21:47 UTC 2026


#65320: WordPress 7 core update silently truncates filenames longer than 100
characters during extraction (wp-includes/php-ai-client/ affected)
--------------------------+-----------------------------
 Reporter:  arakelxvi     |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  General       |    Version:  7.0
 Severity:  major         |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 == Description ==

   When updating to WordPress 7 — either via the admin dashboard or WP-CLI
 — files whose path within the archive exceeds 100 characters are extracted
 with silently truncated
   filenames. No error is reported. WordPress 7 introduced wp-includes/php-
 ai-client/, a new AI client library containing many files with archive-
 internal paths of 101–131
   characters. Every file exceeding the 100-char boundary is extracted with
 a truncated name, causing every WordPress 7 installation to immediately
 fail wp core verify-checksums.

   == Environment ==

   - '''WordPress version:''' 7.0
   - '''PHP version:''' multiple tested — issue is not PHP version specific
   - '''OS:''' Ubuntu Linux
   - '''Reproduction:''' 100% reproducible on every fresh install or update
 to WP7

   == Steps to Reproduce ==

   1. Update to WordPress 7 via admin dashboard or wp core update --allow-
 root
   2. Run wp core verify-checksums --allow-root

   == Expected Behavior ==

   All files extracted with correct full filenames. wp core verify-
 checksums passes.

   == Actual Behavior ==

   Files with archive-internal paths exceeding 100 characters are extracted
 with silently truncated names. wp core verify-checksums reports each
 affected file twice:

   {{{
   Warning: File doesn't exist: wp-includes/php-ai-client/third-
 party/Http/Discovery/Exception/PuliUnavailableException.php
   Warning: File should not exist: wp-includes/php-ai-client/third-
 party/Http/Discovery/Exception/PuliUnavailableException.ph
   Warning: File doesn't exist: wp-includes/php-ai-client/third-
 party/Http/Discovery/Exception/StrategyUnavailableException.php
   Warning: File should not exist: wp-includes/php-ai-client/third-
 party/Http/Discovery/Exception/StrategyUnavailableExceptio
   Warning: File doesn't exist: wp-includes/php-ai-
 client/src/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompatibleModelMetadataDirectory.php
   Warning: File should not exist: wp-includes/php-ai-
 client/src/Providers/OpenAiCompatibleImplementation/AbstractOpenAiCompa
   }}}

   The truncation point is exactly 100 characters of the archive-internal
 path in every case. All files with archive-internal paths ≤ 100 chars
 extract correctly. All files exceeding
    100 chars are affected.

   == Root Cause ==

   PHP's PharData (used for tar.gz extraction) reads only the 100-byte name
 field from tar headers, ignoring the prefix field and PAX extended headers
 that carry the full path for
   entries exceeding 100 characters. This is a known limitation of PHP's
 libphar implementation.

   '''Confirmed:''' PHP reads filenames truncated via PharData, while
 system tools extract correctly:

   {{{#!sh
   PharData — truncated at 100 chars

   php -r "
   $phar = new PharData('/tmp/wp7.tar.gz');
   foreach (new RecursiveIteratorIterator($phar) as $f) {
       if (strpos($f->getPathName(), 'PuliUnavailable') !== false)
           echo $f->getPathName() . PHP_EOL;
   }
   "
   Result: phar:///tmp/wp7.tar.gz/wordpress/.../PuliUnavailableException.ph
 (truncated)

   system tar — correct

   tar -tvf /tmp/wp7.tar.gz | grep PuliUnavailable
   Result: wordpress/.../PuliUnavailableException.php  (correct)

   }}}

   {{{#!sh
   ZipArchive (.zip) — correct

   php -r "
   $z = new ZipArchive();
   $z->open('/tmp/wp7.zip');
   for ($i = 0; $i < $z->numFiles; $i++) {
       $name = $z->getNameIndex($i);
       if (strpos($name, 'PuliUnavailable') !== false)
           echo strlen($name) . ' ' . $name . PHP_EOL;
   }
   $z->close();
   "
   Result: 101 wordpress/.../PuliUnavailableException.php  (correct)

   }}}

   phar:///tmp/wp7.tar.gz/ = 23 chars + 100-char tar name field = 123 chars
 total. The character at position 101 of the internal path is silently
 dropped.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/65320>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list