veilletech.fr
3 sept. Feed du jour
#04 LARAVEL Article

Laravel confine Storage::path au disque

Une mise à jour mineure qui peut casser votre code. Lisez-la.

Laravel 13.30 confine Storage::path() à la racine du disque : un chemin contenant des segments « .. » lève désormais PathTraversalDetected au lieu de retourner un chemin hors du disque. La version ajoute aussi Collection::chunkBy() et fait dire à queue:work la raison de son arrêt.

2 min de lectureintermédiairevidéo 1:19
Partager
Sommaire5 sections
  1. Ce qui change vraiment
  2. chunkBy() sur les collections
  3. queue:work dit pourquoi il s'arrête
  4. Le reste de la version
  5. À retenir

Ce qui change vraiment

Tous les appels du système de fichiers passent par le pilote Flysystem, qui normalise le chemin et lève PathTraversalDetected s'il résout hors de la racine du disque. Un seul y échappait : Storage::path(), qui remettait la chaîne telle quelle au PathPrefixer — lequel se contente de concaténer.

PHP
Storage::get('../../../.env');  // refusé
Storage::path('../../../.env'); // résolvait hors du disque

Sur le disque local par défaut, path() renvoyait donc un chemin natif pointant sur le .env de l'application, là où get(), delete() et readStream() refusaient le même argument. Le danger apparaît dès que le chemin vient de l'extérieur :

PHP
response()->download(Storage::path($request->query('path')));

En 13.30, path() fait passer son argument par WhitespacePathNormalizer, le normalisateur que League\Flysystem\Filesystem construit pour tous les autres appels. Contribution de Kiril Manasijev, PR #61343.

L'effet de bord est réel : le code qui s'appuyait sur path() pour accepter des segments .. ne recevra plus une chaîne, il recevra une exception. À vérifier avant de déployer.

chunkBy() sur les collections

chunkWhile() existait déjà, et la comparaison qu'on y écrivait neuf fois sur dix était toujours la même : l'élément courant contre le dernier du groupe en cours. chunkBy() est cette comparaison, en méthode.

PHP
$products->chunkBy('parent');

collect([1, 1, 2, 2, 1, 1])->chunkBy(fn ($value) => $value);
// [[1, 1], [2, 2], [1, 1]]

La clé passe par data_get(), donc la notation par points fonctionne (chunkBy('address.city')), et les clés d'origine sont préservées dans chaque groupe. Attention à la nuance : c'est un regroupement d'éléments adjacents, pas un groupBy() — d'où trois groupes ci-dessus, et non deux. Contribution de Joseph Silber, PR #61357.

queue:work dit pourquoi il s'arrête

L'événement WorkerStopping portait déjà un WorkerStopReason, mais le lire imposait d'enregistrer un écouteur — beaucoup de plomberie pour une question qu'on se pose en regardant un terminal. La raison est maintenant écrite en dernière ligne :

TEXT
2026-09-01 13:20:40 Worker STOPPED Memory limit exceeded

Avec --json, elle sort en enregistrement structuré :

JSON
{"level":"warning","status":"stopped","reason":"memory","exit_code":12,"jobs_processed":2,"memory":1.2,"timestamp":"2026-09-01T13:20:40.118273+00:00"}

L'énumération WorkerStopReason gagne une méthode description() couvrant neuf scénarios : interruption, perte de connexion, maximum de jobs atteint, limite mémoire, durée maximale, file vide, file vide pendant la durée configurée, signal de redémarrage reçu, job expiré. Rien n'est écrit sous --quiet ni --silent.

Le reste de la version

À retenir

  1. Avant de monter en 13.30, chercher les appels à Storage::path() qui reçoivent des segments relatifs.
  2. chunkBy() remplace le chunkWhile() à callback de comparaison, sur les collections comme sur les lazy collections.
  3. Un worker qui disparaît laisse désormais une trace lisible dans la sortie.

Source : Laravel News