VYPR
High severity8.0NVD Advisory· Published May 14, 2024· Updated Apr 28, 2026

CVE-2024-29800

CVE-2024-29800

Description

Deserialization of Untrusted Data vulnerability in Timber Team & Contributors Timber.This issue affects Timber: from n/a through 1.23.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
timber/timberPackagist
>= 2.0.0, < 2.1.02.1.0
timber/timberPackagist
>= 1.24.0, < 1.24.11.24.1
timber/timberPackagist
>= 0.16.6, < 1.23.11.23.1

Patches

1
13c6b0f60346

fix: Add patch for PHAR deserialization vulnerability for Timber 2.x (security advisory GHSA-6363-v5m4-fvq3)

https://github.com/timber/timberNicolas LemoineApr 10, 2024via ghsa
7 files changed · +136 1
  • src/Attachment.php+5 0 modified
    @@ -2,6 +2,7 @@
     
     namespace Timber;
     
    +use InvalidArgumentException;
     use Timber\Factory\PostFactory;
     
     /**
    @@ -245,6 +246,10 @@ public function size(): ?int
                 return $this->size = (int) $size;
             }
     
    +        if (!ImageHelper::is_protocol_allowed($this->file_loc())) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             /**
              * Filesize wasn't found in the metadata, so we'll try to get it from the file itself.
              *
    
  • src/ImageDimensions.php+6 0 modified
    @@ -2,6 +2,8 @@
     
     namespace Timber;
     
    +use InvalidArgumentException;
    +
     /**
      * Class FileSize
      *
    @@ -117,6 +119,10 @@ public function get_dimension($dimension): ?int
                 return $this->get_dimension_loaded($dimension);
             }
     
    +        if (!ImageHelper::is_protocol_allowed($this->file_loc)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             // Load dimensions.
             if (\file_exists($this->file_loc) && \filesize($this->file_loc)) {
                 if (ImageHelper::is_svg($this->file_loc)) {
    
  • src/ImageHelper.php+60 1 modified
    @@ -2,6 +2,7 @@
     
     namespace Timber;
     
    +use InvalidArgumentException;
     use Timber\Image\Operation;
     
     /**
    @@ -29,6 +30,10 @@ class ImageHelper
     
         public static $home_url;
     
    +    protected const ALLOWED_PROTOCOLS = ['file', 'http', 'https'];
    +
    +    protected const WINDOWS_LOCAL_FILENAME_REGEX = '/^[a-z]:(?:[\\\\\/]?(?:[\w\s!#()-]+|[\.]{1,2})+)*[\\\\\/]?/i';
    +
         /**
          * Inits the object.
          */
    @@ -140,6 +145,11 @@ public static function is_animated_gif($file)
                 //doesn't have .gif, bail
                 return false;
             }
    +
    +        if (!ImageHelper::is_protocol_allowed($file)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             // Its a gif so test
             if (!($fh = @\fopen($file, 'rb'))) {
                 return false;
    @@ -169,7 +179,15 @@ public static function is_animated_gif($file)
          */
         public static function is_svg($file_path)
         {
    -        if ('' === $file_path || !\file_exists($file_path)) {
    +        if ('' === $file_path) {
    +            return false;
    +        }
    +
    +        if (!ImageHelper::is_protocol_allowed($file_path)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
    +        if (!\file_exists($file_path)) {
                 return false;
             }
     
    @@ -431,6 +449,10 @@ public static function get_sideloaded_file_loc($file)
          */
         public static function sideload_image($file)
         {
    +        if (!ImageHelper::is_protocol_allowed($file)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             /**
              * Adds a filter to change the upload folder temporarily.
              *
    @@ -444,6 +466,7 @@ public static function sideload_image($file)
             \add_filter('upload_dir', [__CLASS__, 'set_sideload_image_upload_dir']);
     
             $loc = self::get_sideloaded_file_loc($file);
    +
             if (\file_exists($loc)) {
                 $url = URLHelper::file_system_to_url($loc);
     
    @@ -806,6 +829,10 @@ private static function _operate($src, $op, $force = false)
                 return '';
             }
     
    +        if (!ImageHelper::is_protocol_allowed($src)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             $allow_fs_write = \apply_filters('timber/allow_fs_write', true);
     
             if ($allow_fs_write === false) {
    @@ -949,4 +976,36 @@ public static function get_resize_file_path($url, $w, $h, $crop)
             );
             return $new_path;
         }
    +
    +    /**
    +     * Checks if the protocol of the given filename is allowed.
    +     *
    +     * This fixes a security issue with a PHAR deserialization vulnerability
    +     * with file_exists() in PHP < 8.0.0.
    +     *
    +     * @param  string $filepath File path.
    +     * @return bool
    +     */
    +    public static function is_protocol_allowed($filepath)
    +    {
    +        $parsed_url = \parse_url($filepath);
    +
    +        if (false === $parsed_url) {
    +            throw new InvalidArgumentException('The filename is not valid.');
    +        }
    +
    +        $protocol = isset($parsed_url['scheme'])
    +            ? \mb_strtolower($parsed_url['scheme'])
    +            : 'file';
    +
    +        if (
    +            \PHP_OS_FAMILY === 'Windows'
    +            && \strlen($protocol) === 1
    +            && \preg_match(self::WINDOWS_LOCAL_FILENAME_REGEX, $filepath)
    +        ) {
    +            $protocol = 'file';
    +        }
    +
    +        return \in_array($protocol, self::ALLOWED_PROTOCOLS, true);
    +    }
     }
    
  • src/Image/Operation/ToJpg.php+5 0 modified
    @@ -2,6 +2,7 @@
     
     namespace Timber\Image\Operation;
     
    +use InvalidArgumentException;
     use Timber\Image\Operation as ImageOperation;
     use Timber\ImageHelper;
     
    @@ -44,6 +45,10 @@ public function filename($src_filename, $src_extension = 'jpg')
          */
         public function run($load_filename, $save_filename)
         {
    +        if (!ImageHelper::is_protocol_allowed($load_filename)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             if (!\file_exists($load_filename)) {
                 return false;
             }
    
  • src/Image/Operation/ToWebp.php+5 0 modified
    @@ -2,6 +2,7 @@
     
     namespace Timber\Image\Operation;
     
    +use InvalidArgumentException;
     use Timber\Helper;
     use Timber\Image\Operation as ImageOperation;
     use Timber\ImageHelper;
    @@ -45,6 +46,10 @@ public function filename($src_filename, $src_extension = 'webp')
          */
         public function run($load_filename, $save_filename)
         {
    +        if (!ImageHelper::is_protocol_allowed($load_filename)) {
    +            throw new InvalidArgumentException('The output file scheme is not supported.');
    +        }
    +
             if (!\is_file($load_filename)) {
                 return false;
             }
    
  • src/Timber.php+5 0 modified
    @@ -2,6 +2,7 @@
     
     namespace Timber;
     
    +use InvalidArgumentException;
     use Timber\Factory\CommentFactory;
     use Timber\Factory\MenuFactory;
     use Timber\Factory\PagesMenuFactory;
    @@ -659,6 +660,10 @@ public static function get_attachment_by(string $field_or_ident, string $ident =
                     return null;
                 }
     
    +            if (!ImageHelper::is_protocol_allowed($ident)) {
    +                throw new InvalidArgumentException('The output file scheme is not supported.');
    +            }
    +
                 if (!\file_exists($ident)) {
                     // Deal with a relative path.
                     $ident = URLHelper::get_full_path($ident);
    
  • tests/test-timber-image.php+50 0 modified
    @@ -1185,4 +1185,54 @@ public function testSVGDimensions()
             $this->assertSame(23, $image->width());
             $this->assertSame(20, $image->height());
         }
    +
    +    public function testPharProtocolIsNotAllowedwithResize()
    +    {
    +        $object = new ImageOperation\Resize(400, 300, 'center');
    +        $load_filename = 'phar://test.jpg';
    +        $save_filename = 'test-new.jpg';
    +
    +        $this->expectException(InvalidArgumentException::class);
    +        $object->run($load_filename, $save_filename);
    +    }
    +
    +    public function testPharProtocolIsNotAllowedwithLetterbox()
    +    {
    +        $object = new ImageOperation\Letterbox(400, 300, '#FFFFFF');
    +        $load_filename = 'phar://test.jpg';
    +        $save_filename = 'test-new.jpg';
    +
    +        $this->expectException(InvalidArgumentException::class);
    +        $object->run($load_filename, $save_filename);
    +    }
    +
    +    public function testPharProtocolIsNotAllowedwithRetina()
    +    {
    +        $object = new ImageOperation\Retina(2);
    +        $load_filename = 'phar://test.jpg';
    +        $save_filename = 'test-new.jpg';
    +
    +        $this->expectException(InvalidArgumentException::class);
    +        $object->run($load_filename, $save_filename);
    +    }
    +
    +    public function testPharProtocolIsNotAllowedwithToJpg()
    +    {
    +        $object = new ImageOperation\ToJpg('#FFFFFF');
    +        $load_filename = 'phar://test.svg';
    +        $save_filename = 'test-new.svg';
    +
    +        $this->expectException(InvalidArgumentException::class);
    +        $object->run($load_filename, $save_filename);
    +    }
    +
    +    public function testPharProtocolIsNotAllowedwithToWebp()
    +    {
    +        $object = new ImageOperation\ToWebp(80);
    +        $load_filename = 'phar://test.png';
    +        $save_filename = 'test-new.png';
    +
    +        $this->expectException(InvalidArgumentException::class);
    +        $object->run($load_filename, $save_filename);
    +    }
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.