Si vous venez de glisser un fichier dans la médiathèque et que WordPress vous répond sèchement “Sorry, this file type is not permitted for security reasons.”, vous n’êtes pas seul. Je vois ce blocage très souvent sur des sites Elementor/Divi/Avada après une mise à jour, une migration d’hébergement, ou quand on tente d’uploader un format “un peu spécial” (SVG, JSON, WebP mal détecté, polices .woff2, etc.).

Le problème

Le message apparaît généralement dans l’administration, au moment d’ajouter un média (Médiathèque → Ajouter) ou quand un constructeur de pages (Elementor, Divi 5, Avada/Fusion Builder) envoie un fichier via sa propre interface d’upload.

Message typique (selon la langue du site) :

Sorry, this file type is not permitted for security reasons.

Ou en français :

Désolé, ce type de fichier n’est pas autorisé pour des raisons de sécurité.

Ce que vous saurez faire à la fin :

  • identifier quel type MIME WordPress refuse réellement (ce n’est pas toujours l’extension)
  • autoriser un format de manière propre (sans ouvrir une faille)
  • corriger les cas où le serveur ou PHP détecte un MIME “bizarre”
  • diagnostiquer un conflit plugin/sécurité/caching qui bloque l’upload

Résumé rapide

  • WordPress 6.9.4 bloque certains fichiers parce que le type MIME n’est pas dans la liste autorisée ou parce que la détection MIME est incohérente.
  • La solution la plus propre passe par le filtre upload_mimes (autoriser une extension) et parfois wp_check_filetype_and_ext (corriger la détection).
  • Évitez les “solutions” qui autorisent tout : c’est une porte ouverte aux malwares.
  • Si vous essayez d’uploader du SVG, traitez-le comme un cas à part : il faut sanitizer (nettoyer) le contenu.
  • En cas de doute : testez sans plugins via Health Check, vérifiez les logs, et inspectez le MIME réellement détecté.

Les symptômes

Selon le contexte, vous pouvez voir :

  • Le message “file type is not permitted” dès la sélection du fichier.
  • Un upload qui “tourne” puis échoue, parfois avec un message plus vague (“Une erreur est survenue lors de l’envoi”).
  • Dans Elementor/Divi/Avada : l’interface indique “Upload failed” alors que la médiathèque WordPress affiche l’erreur de type non autorisé.
  • Des différences entre local et production : en local ça passe, sur le serveur non.
  • Des erreurs dans les logs PHP ou serveur si la sécurité (WAF) bloque le fichier (souvent avec des SVG ou des JSON).

Table de diagnostic rapide (utile quand vous ne savez pas “par où attaquer”) :

Symptôme Cause probable Vérification Solution
Erreur immédiate sur .svg SVG non autorisé (et risque XSS) Essayez un .jpg : s’il passe, c’est bien un blocage de type Solution 1 + méthode SVG sécurisée (sanitization)
.webp refusé sur un site, accepté sur un autre MIME détecté différemment selon PHP/serveur Inspecter le MIME détecté via un petit snippet Solution 2 (corriger wp_check_filetype_and_ext)
.json / .csv refusé Non autorisé par défaut Vérifier extension + besoin réel (import/export) Solution 1 (autoriser extension) + limiter aux admins
Tout est refusé (même .jpg) Conflit plugin sécurité / WAF / droits fichiers Test Health Check + logs + permissions Solution 3 + “Si ça ne marche toujours pas”

Pourquoi ça arrive

Explication simple (débutants)

WordPress ne se contente pas de regarder l’extension (.svg, .json, .woff2). Il essaie de vérifier le type réel du fichier (le type MIME, par exemple image/svg+xml ou application/json). Si ce type n’est pas autorisé (ou si WordPress n’arrive pas à le confirmer), il bloque l’upload.

Ce blocage est volontaire : autoriser “n’importe quoi” permettrait d’uploader des fichiers dangereux (scripts, HTML malveillant, SVG contenant du JavaScript, etc.).

Explication technique (intermédiaires / pros)

Au moment de l’upload, WordPress utilise une combinaison de :

  • la liste des MIMEs autorisés (upload_mimes)
  • la détection de type via PHP (selon l’hébergement : fileinfo, configuration serveur)
  • une validation extension ↔ MIME via wp_check_filetype_and_ext

Le même symptôme peut venir de causes différentes. Voici les causes, du plus fréquent au plus rare :

  • Format non autorisé par défaut (SVG, JSON, CSV, AI/PSD, polices, etc.).
  • MIME mal détecté (hébergeur, module PHP manquant, fichier “non standard”).
  • Plugin de sécurité (ou WAF type ModSecurity/Cloudflare) qui bloque l’upload.
  • Snippet d’un ancien tutoriel qui utilise un hook inadapté ou autorise trop/incorrectement.
  • Permissions/ownership sur wp-content/uploads qui provoquent un comportement erratique (moins courant pour ce message précis, mais je l’ai vu).

Prérequis avant de commencer

  • Sauvegarde : faites une sauvegarde fichiers + base de données avant de toucher au code.
  • Ne modifiez jamais le core : pas de modifications dans wp-includes / wp-admin.
  • Version cible : WordPress 6.9.4 (avril 2026) et PHP 8.1+.
  • Outils utiles :
  • Mode debug (temporaire) : activez WP_DEBUG si vous devez lire des erreurs. Doc officielle : Debug WordPress.

Où coller le code ?

  • Idéal : un mini-plugin (recommandé), ou un mu-plugin (chargé automatiquement).
  • Acceptable : functions.php d’un thème enfant (pas le thème parent).
  • À éviter : un plugin de “snippets” si vous avez déjà eu des snippets qui cassent le site (ça arrive).

Solution 1 : Autoriser un type de fichier proprement (MIME) avec le bon filtre

Cette solution règle le cas le plus courant : le format n’est pas autorisé par WordPress, point.

Avant : le “mauvais” snippet (trop permissif)

J’ai souvent vu des tutoriels qui proposent d’autoriser tous les types, ou qui ajoutent des MIMEs sans restriction de rôle. C’est dangereux.

<?php
// ❌ Exemple à ne pas utiliser : autorise (presque) tout, sans contrôle.
// On voit encore ce snippet sur des blogs anciens.
add_filter('upload_mimes', function ($mimes) {
    return array_merge($mimes, array(
        'svg'  => 'image/svg+xml',
        'json' => 'application/json',
        'exe'  => 'application/x-msdownload', // 🔥 très mauvaise idée
    ));
});

Pourquoi c’est cassé (ou risqué) :

  • Vous autorisez des types qui ne devraient jamais passer (ex. .exe).
  • Vous ne limitez pas qui peut uploader ces fichiers.
  • Pour certains formats (SVG), autoriser l’extension ne suffit pas : il faut aussi nettoyer le contenu.

Après : autoriser un format précis + limiter aux admins

Créez un mu-plugin (recommandé) :

  • Créez le dossier wp-content/mu-plugins/ s’il n’existe pas.
  • Créez le fichier wp-content/mu-plugins/bpcab-uploads-mimes.php.

Sauvegardez avant de modifier.

<?php
/**
 * Plugin Name: BPCAB - Autoriser certains types de fichiers à l'upload
 * Description: Autorise des extensions spécifiques (ex: json, csv, woff2) uniquement pour les administrateurs.
 * Author: Vous
 * Version: 1.0.0
 *
 * Sécurité : ne jamais autoriser "tout". Ajoutez seulement les types nécessaires.
 */

defined('ABSPATH') || exit;

/**
 * Filtre (filter) : un "filtre" WordPress reçoit une valeur, la modifie et la renvoie.
 * Ici, on filtre la liste des MIMEs autorisés à l'upload.
 */
add_filter('upload_mimes', function (array $mimes): array {

    // Limite simple : uniquement les administrateurs.
    // (Vous pouvez adapter selon votre besoin : éditeurs, auteurs, etc.)
    if (!current_user_can('manage_options')) {
        return $mimes;
    }

    // Ajoutez uniquement ce dont vous avez besoin.
    // Exemples courants :
    $mimes['json']  = 'application/json';
    $mimes['csv']   = 'text/csv';
    $mimes['woff2'] = 'font/woff2';
    $mimes['woff']  = 'font/woff';

    // ⚠️ SVG : à éviter sans nettoyage. Voir plus bas.
    // $mimes['svg'] = 'image/svg+xml';

    return $mimes;
}, 10);

Pourquoi ça corrige le problème

WordPress consulte cette liste au moment de valider le fichier. Si l’extension n’existe pas dans la liste (ou si le MIME associé ne colle pas), l’upload est refusé.

Explication bloc par bloc

  • add_filter('upload_mimes', ...) : vous modifiez la liste des MIMEs autorisés.
  • current_user_can('manage_options') : vous limitez l’autorisation aux administrateurs (réduit l’impact sécurité).
  • $mimes['woff2'] = 'font/woff2' : vous associez l’extension à un type MIME.

Cas particulier : autoriser le SVG (avec sécurité minimale)

Le SVG est un fichier texte pouvant contenir du JavaScript. Autoriser le SVG “brut” est une source classique de XSS (injection de script). Si vous devez absolument le faire, faites-le au minimum :

  • uniquement pour les admins
  • en nettoyant le contenu via une librairie spécialisée

Sans dépendance externe, WordPress core ne fournit pas un “sanitizer SVG” complet. Dans la pratique, utilisez un plugin réputé qui sanitize (voir “Variante / alternative”). Si vous insistez pour le faire en code, faites-le dans un plugin custom avec une librairie éprouvée (et testée), pas avec un regex.


Solution 2 : Corriger un MIME détecté faux (ou incomplet) côté WordPress

Parfois, vous avez déjà autorisé l’extension via upload_mimes, mais l’erreur continue. Dans ce cas, WordPress rejette le fichier parce que la détection réelle du type ne correspond pas à ce qui est attendu.

Exemples que j’ai déjà rencontrés :

  • un .csv détecté comme text/plain selon l’hébergeur
  • un .json détecté comme text/plain
  • des polices .woff2 détectées en application/octet-stream

Avant : autoriser l’extension… mais l’upload échoue quand même

<?php
// ✅ Extension autorisée, mais certains serveurs continuent de bloquer
// si la détection MIME ne correspond pas.
add_filter('upload_mimes', function ($mimes) {
    $mimes['woff2'] = 'font/woff2';
    return $mimes;
});

Après : utiliser wp_check_filetype_and_ext pour réconcilier extension et MIME

Ajoutez ce code dans le même mu-plugin que la Solution 1 (ou dans un plugin custom). Sauvegardez avant de modifier.

<?php
defined('ABSPATH') || exit;

/**
 * Filtre avancé : WordPress vérifie l'extension ET le MIME détecté.
 * On peut corriger certains cas où le serveur renvoie un MIME trop générique.
 *
 * Doc : https://developer.wordpress.org/reference/hooks/wp_check_filetype_and_ext/
 */
add_filter('wp_check_filetype_and_ext', function (array $data, string $file, string $filename, array $mimes): array {

    // Toujours limiter aux admins : on évite d'élargir la surface d'attaque.
    if (!is_user_logged_in() || !current_user_can('manage_options')) {
        return $data;
    }

    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

    // Si WordPress n'arrive pas à identifier correctement, on aide pour des cas précis.
    // Attention : on ne "force" pas si l'extension est absente.
    if ($ext === 'woff2') {
        $data['ext']  = 'woff2';
        $data['type'] = 'font/woff2';
    }

    if ($ext === 'woff') {
        $data['ext']  = 'woff';
        $data['type'] = 'font/woff';
    }

    if ($ext === 'json') {
        $data['ext']  = 'json';
        $data['type'] = 'application/json';
    }

    if ($ext === 'csv') {
        $data['ext']  = 'csv';
        // Selon les environnements, text/csv ou application/csv peuvent exister.
        // WordPress accepte si ça correspond à votre upload_mimes.
        $data['type'] = 'text/csv';
    }

    return $data;
}, 10, 4);

Pourquoi ça corrige le problème

Le filtre wp_check_filetype_and_ext intervient au moment où WordPress compare :

  • l’extension du fichier
  • le MIME “autorisé”
  • le MIME “détecté” par PHP/serveur

Quand un hébergeur renvoie un MIME trop générique (application/octet-stream), WordPress peut refuser même si l’extension est autorisée. Ici, vous “stabilisez” la détection pour des extensions ciblées.

Note compatibilité Divi 5 / Elementor / Avada

Ces constructeurs utilisent l’uploader WordPress (ou des endpoints admin-ajax/REST qui finissent par passer par les mêmes validations). Une fois le MIME accepté côté WordPress, l’upload fonctionne en général aussi dans Divi 5, Elementor et Avada. Si ça échoue uniquement dans le builder, regardez “Si ça ne marche toujours pas” : c’est souvent un conflit de sécurité, de nonce, ou de cache.


Solution 3 : Diagnostic avancé (WP-CLI, serveur, sécurité)

Si le message apparaît même pour des fichiers standard (JPG/PNG), ou si vos solutions en code ne changent rien, je pars sur un diagnostic “infrastructure”.

Étape 1 : vérifier la santé du site et isoler les plugins (sans casser le site public)

Installez Health Check & Troubleshooting, puis activez le mode dépannage. Cela désactive plugins/thème uniquement pour votre session.

Test :

  1. Passez en mode dépannage.
  2. Essayez d’uploader un fichier qui échoue.
  3. Réactivez vos plugins un par un.

Si l’upload redevient possible en mode dépannage, vous avez un conflit plugin (souvent sécurité, optimisation, ou un plugin “media”).

Étape 2 : vérifier si un WAF / ModSecurity bloque l’upload

Les SVG et certains JSON déclenchent des règles WAF. Symptôme classique : WordPress affiche “type non autorisé”, mais le vrai blocage est côté serveur.

Vérifications :

  • Regardez les logs du serveur (Apache/Nginx) et du WAF si vous y avez accès.
  • Si vous êtes sur un hébergement managé, demandez explicitement : “une règle ModSecurity bloque-t-elle l’upload de fichiers image/svg+xml ?”.

Étape 3 : contrôler PHP et l’extension fileinfo

La détection MIME s’appuie souvent sur l’extension PHP fileinfo. Si elle est absente ou mal configurée, la détection peut être incohérente.

Doc PHP : Fileinfo.

Si vous avez WP-CLI, vous pouvez au minimum vérifier la version :

php -v

Et côté WordPress (WP-CLI) :

wp --info

Étape 4 : vérifier les permissions du dossier uploads

Ce n’est pas la cause la plus fréquente de ce message, mais j’ai déjà vu des permissions cassées entraîner des retours d’erreurs “bizarres” côté uploader.

  • wp-content/uploads doit être inscriptible par l’utilisateur du serveur web.

Si vous avez un accès shell :

ls -ld wp-content/uploads
find wp-content/uploads -maxdepth 2 -type d -print -exec ls -ld {} ;

Vérifications après correction

Après avoir appliqué une solution, testez de façon reproductible :

  1. Déconnectez-vous puis reconnectez-vous (les capacités utilisateur peuvent être mises en cache par certains plugins).
  2. Testez l’upload dans :
    • Médiathèque WordPress
    • votre builder (Elementor / Divi 5 / Avada) si vous l’utilisez
  3. Testez avec 2 fichiers :
    • un fichier standard (JPG)
    • le fichier problématique (ex. WOFF2/JSON/CSV)
  4. Videz les caches :
    • cache plugin (si présent)
    • cache serveur/CDN (si présent)
    • cache navigateur (ou test en navigation privée)

Résultat attendu :

  • Le fichier apparaît dans la médiathèque.
  • Vous pouvez le sélectionner dans le builder.
  • Aucun warning PHP dans Query Monitor (sinon, corrigez avant de continuer).

Si ça ne marche toujours pas

Voici ma procédure “terrain”, dans l’ordre. Ne sautez pas d’étapes : on perd du temps sinon.

1) Confirmez le type réellement détecté

Quand vous pensez uploader “un JSON”, WordPress peut voir “text/plain”. Pour le confirmer proprement, ajoutez temporairement un petit outil d’admin (et supprimez-le après).

Dans un mu-plugin (temporaire), ajoutez un menu qui affiche ce que WordPress détecte pour un fichier donné. C’est volontairement minimal.

<?php
/**
 * ⚠️ Outil temporaire : affiche le type détecté pour un fichier sur le serveur.
 * À supprimer après diagnostic.
 */
defined('ABSPATH') || exit;

add_action('admin_menu', function () {
    add_management_page(
        'Diagnostic MIME',
        'Diagnostic MIME',
        'manage_options',
        'bpcab-mime-diagnostic',
        function () {
            if (!current_user_can('manage_options')) {
                return;
            }

            echo '<div class="wrap"><h2>Diagnostic MIME</h2>';

            $upload_dir = wp_upload_dir();
            $test_file  = trailingslashit($upload_dir['basedir']) . 'mime-test.json';

            echo '<p>Chemin de test : <code>' . esc_html($test_file) . '</code></p>';

            if (!file_exists($test_file)) {
                echo '<p>Créez un fichier <code>mime-test.json</code> dans le dossier uploads (même vide) puis rechargez.</p>';
                echo '</div>';
                return;
            }

            $check = wp_check_filetype_and_ext($test_file, basename($test_file));

            echo '<p>Résultat <code>wp_check_filetype_and_ext</code> :</p>';
            echo '<pre><code class="language-php">' . esc_html(print_r($check, true)) . '</code></pre>';

            echo '<p>Pensez à supprimer cet outil après usage.</p>';
            echo '</div>';
        }
    );
});

Si type est vide ou inattendu, Solution 2 est généralement la bonne piste, ou bien un problème PHP/serveur.

2) Testez sans plugins (Health Check)

Si en mode dépannage l’upload fonctionne, vous avez un plugin coupable. Les suspects habituels :

  • plugins de sécurité (blocage MIME, scan upload)
  • plugins de cache/optimisation qui touchent à l’admin-ajax ou REST
  • plugins “media” (offload S3, compression, WebP, etc.)

3) Vérifiez WP_DEBUG et les logs

Activez temporairement WP_DEBUG_LOG pour capturer des warnings/erreurs lors de l’upload. Doc : Debug WordPress.

4) Vérifiez la mémoire PHP et la taille d’upload

Ce n’est pas exactement le même message, mais beaucoup confondent. Si votre fichier est gros, vous verrez plutôt une erreur de taille. Vérifiez :

  • upload_max_filesize
  • post_max_size
  • memory_limit

Doc PHP : php.ini directives.

5) Vérifiez un conflit de priorité de hook

Si un plugin modifie aussi upload_mimes, votre filtre peut être écrasé.

  • Essayez une priorité plus élevée (ex. 20 ou 99).
<?php
add_filter('upload_mimes', function (array $mimes): array {
    if (!current_user_can('manage_options')) {
        return $mimes;
    }
    $mimes['json'] = 'application/json';
    return $mimes;
}, 99);

Pièges et erreurs courantes

Symptôme Cause probable Solution recommandée
Vous collez le code dans le mauvais fichier Code mis dans le thème parent (perdu à la prochaine mise à jour) Utilisez un mu-plugin ou un thème enfant
Erreur PHP après ajout du snippet Point-virgule manquant, parenthèse oubliée Revenez en arrière via FTP, corrigez, testez sur staging
Le snippet ne “marche pas” Hook inadapté (ex. vous utilisez une action au lieu d’un filtre) Utilisez upload_mimes (filtre) et non une action
Ça marche en admin, pas dans Elementor/Divi Blocage WAF/nonce/caching sur l’endpoint du builder Test Health Check, désactivez sécurité/caches, vérifiez console navigateur
Vous autorisez SVG et vous vous faites peur SVG non nettoyé (XSS possible) Plugin de sanitization SVG + restriction admin uniquement
Ancien tuto qui dit “définissez ALLOW_UNFILTERED_UPLOADS” Déverrouille trop, risque sécurité élevé Évitez. Préférez des MIMEs ciblés + contrôle de rôle
Le problème revient après migration Le nouveau serveur détecte les MIMEs différemment Solution 2 + vérification extension fileinfo

Variante / alternative

Méthode sans code : plugin (utile pour débutants)

Si vous ne voulez pas toucher au code, utilisez un plugin qui gère les types de fichiers de façon explicite. Cherchez un plugin “File Upload Types” sur le répertoire officiel, vérifiez :

  • dernière mise à jour récente
  • compatibilité déclarée avec votre version de WordPress
  • notes de sécurité (particulièrement pour SVG)

Répertoire officiel : WordPress Plugins.

Méthode plus avancée : plugin custom + règles strictes

Pour un site pro, je préfère un plugin custom (ou mu-plugin) versionné, avec :

  • liste blanche stricte (whitelist) des extensions
  • restriction par rôle
  • sanitization quand nécessaire (SVG)
  • journalisation (log) des uploads refusés si vous êtes en environnement sensible

Éviter ce problème à l’avenir

  • N’autorisez que ce dont vous avez besoin. Si vous avez besoin de JSON uniquement pour un import ponctuel, autorisez-le temporairement, puis retirez-le.
  • Évitez les snippets “magiques” d’anciens tutoriels. Beaucoup datent d’avant les contrôles MIME plus stricts et contournent la sécurité au lieu de travailler avec les filtres prévus.
  • Gardez PHP à jour (8.1+ minimum recommandé) : la détection MIME et la sécurité en dépendent.
  • Testez sur staging avant production, surtout si vous touchez aux uploads.
  • Surveillez les plugins de sécurité : certains ajoutent leurs propres listes de blocage. Après mise à jour, re-testez vos uploads “non standards”.

Si vous utilisez un builder (Divi 5 / Elementor / Avada), gardez en tête : ces outils multiplient les points d’entrée (AJAX/REST). Un cache agressif ou une règle WAF peut casser l’upload dans le builder alors que la médiathèque fonctionne.


Ressources


Questions fréquentes

Le message veut dire que mon fichier est “dangereux” ?

Pas forcément. Il veut dire que WordPress n’a pas pu confirmer que ce type de fichier est autorisé (liste blanche) et cohérent (extension ↔ MIME). Pour certains formats (SVG), le risque est réel.

Est-ce que je peux autoriser n’importe quel type de fichier ?

Techniquement oui, mais c’est une mauvaise idée. Autoriser des types exécutables ou interprétables augmente fortement le risque de compromission. Restez sur une liste blanche minimale.

Pourquoi ça marche sur mon site de test mais pas en production ?

Parce que la détection MIME dépend de l’hébergement (PHP, modules, WAF). C’est un grand classique après migration.

J’ai autorisé l’extension avec upload_mimes, mais l’erreur reste. Pourquoi ?

Souvent parce que le MIME détecté ne correspond pas. Utilisez la Solution 2 avec wp_check_filetype_and_ext pour des extensions ciblées, ou corrigez la config serveur.

Elementor (ou Divi/Avada) refuse, mais la médiathèque accepte. Que faire ?

Regardez la console navigateur (onglet Network) et testez en mode dépannage (Health Check). C’est fréquemment un plugin de sécurité/caching qui bloque l’appel AJAX/REST du builder.

Autoriser SVG est-il vraiment risqué ?

Oui. Un SVG peut contenir du code scriptable. Si vous devez l’autoriser, limitez aux admins et utilisez un plugin ou une librairie qui nettoie le SVG avant stockage.

Où dois-je coller le code exactement ?

Le plus fiable : wp-content/mu-plugins/ dans un fichier .php. Sinon, dans le functions.php d’un thème enfant. Évitez le thème parent.

Dois-je régénérer les permaliens ?

Non pour ce problème. La réécriture d’URL (rewrite rules) n’a généralement rien à voir avec la validation des uploads.

Est-ce que vider le cache peut aider ?

Oui, surtout si un plugin met en cache des réponses admin-ajax/REST ou si un CDN/WAF applique des règles. Après modification, videz cache plugin + CDN et retestez en navigation privée.