Skip to content

Erreur 403 sur hébergement mutualisé OVH (ModSecurity) #4600

@phardouin

Description

@phardouin

Bug: Erreur 403 sur hébergement mutualisé OVH (ModSecurity)

Description du problème

Sur un hébergement mutualisé OVH avec ModSecurity activé, toutes les requêtes AJAX échouent avec une erreur HTTP 403 Forbidden lors de :

  • L'ajout de risques
  • L'ajout de tâches
  • L'ajout d'évaluations
  • L'enregistrement de métadonnées (après upload d'images)

Cause

Le pare-feu applicatif ModSecurity bloque les requêtes POST avec Content-Type: text/plain, qui est automatiquement généré par jQuery lorsque :

  • contentType: false est utilisé
  • AVEC data: JSON.stringify(...)

Log ModSecurity :
[id "960010"] [msg "Request content type is not allowed by policy"] [data "text/plain"]

Fichiers concernés

Digirisk :

  • js/modules/risk.js (lignes 188, 271, 322)
  • js/modules/task.js (7 occurrences)
  • js/modules/riskAssessment.js (3 occurrences)

Saturne :

  • js/modules/mediaGallery.js (lignes 146, 238, 309, 596, 611, 679, 717, 751, 785)
  • js/modules/utils.js
  • js/modules/audio.js
  • js/modules/dashboard.js
  • js/modules/dragable.js

Solution

Pour les requêtes qui envoient du JSON avec JSON.stringify() :
❌ Incorrect :

$.ajax({
    data: JSON.stringify({...}),
    processData: false,
    contentType: false,  // Génère "text/plain"
});

✅ Correct :

$.ajax({
    data: JSON.stringify({...}),
    processData: false,
    contentType: 'application/json',
});

⚠️ Exception importante :
Pour les uploads de fichiers avec FormData, garder contentType: false :
$.ajax({

    data: formData,  // FormData object
    processData: false,
    contentType: false,  // Correct pour multipart/form-data
});

Environnement

Dolibarr : 21.0.1
Digirisk : 21.1.0
Hébergement : OVH mutualisé Pro
ModSecurity : Activé (règle CRS 960010)

Impact

  • Ce bug rend Digirisk inutilisable (à partir de la saisie des risques, des tâches, l'upload de photos...) sur les hébergements mutualisés avec ModSecurity (OVH, certains autres hébergeurs).

Reproductibilité

  • 100% sur hébergement OVH mutualisé avec ModSecurity activé.
  • 0% sur serveur local (WAMP/MAMP) ou serveurs sans WAF.

Correction manuelle de ce bug

# Digirisk - Correction globale
cd digiriskdolibarr/
find js/modules/ -name "*.js" -exec sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' {} \;
npx gulp js_backend

# Saturne - Correction avec exceptions
cd ../saturne/
find js/modules/ -name "*.js" ! -name "mediaGallery.js" -exec sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' {} \;

# mediaGallery.js : correction globale puis exceptions
sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' js/modules/mediaGallery.js
sed -i '309s/contentType: '\''application\/json'\'',/contentType: false,/' js/modules/mediaGallery.js
sed -i '596s/contentType: '\''application\/json'\'',/contentType: false,/' js/modules/mediaGallery.js

npx gulp js_backend

# Uploadez les fichiers .min.js générés sur votre serveur
- saturne.min.js
- digiriskdolibarr.min.js

Script de correction de ce bug

#!/bin/bash

# Script de correction du bug ModSecurity sur Digirisk/Saturne
# Auteur: Communauté Digirisk
# Date: Novembre 2025

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Correction bug ModSecurity (HTTP 403)${NC}"
echo -e "${GREEN}========================================${NC}\n"

# Vérifier qu'on est au bon endroit
if [ ! -d "digiriskdolibarr" ] || [ ! -d "saturne" ]; then
    echo -e "${RED}Erreur: Ce script doit être exécuté depuis le dossier parent contenant 'digiriskdolibarr' et 'saturne'${NC}"
    exit 1
fi

# ==========================================
# PARTIE 1: Correction Digirisk
# ==========================================

echo -e "${YELLOW}[1/5] Correction des fichiers Digirisk...${NC}"

# Corriger tous les fichiers JS sauf ceux qui utilisent FormData
find digiriskdolibarr/js/modules/ -name "*.js" -type f | while read file; do
    # Vérifier si le fichier contient contentType: false
    if grep -q "contentType: false" "$file"; then
        sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' "$file"
        echo "  ✓ Corrigé: $file"
    fi
done

# ==========================================
# PARTIE 2: Correction Saturne (avec précaution)
# ==========================================

echo -e "\n${YELLOW}[2/5] Correction des fichiers Saturne...${NC}"

# Fichiers Saturne - Correction générale
find saturne/js/modules/ -name "*.js" ! -name "mediaGallery.js" -type f | while read file; do
    if grep -q "contentType: false" "$file"; then
        sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' "$file"
        echo "  ✓ Corrigé: $file"
    fi
done

# Cas spécial: mediaGallery.js
echo -e "\n${YELLOW}[3/5] Correction spéciale de mediaGallery.js...${NC}"

MEDIA_GALLERY="saturne/js/modules/mediaGallery.js"

if [ -f "$MEDIA_GALLERY" ]; then
    # Correction globale d'abord
    sed -i 's/contentType: false,/contentType: '\''application\/json'\'',/g' "$MEDIA_GALLERY"
    
    # Puis on remet contentType: false pour les vrais uploads de fichiers (lignes avec FormData)
    # On cherche les lignes qui ont "data: formdata" et on remonte pour trouver contentType
    
    # Ligne ~309 (premier upload)
    sed -i '309s/contentType: '\''application\/json'\'',/contentType: false,/' "$MEDIA_GALLERY"
    
    # Ligne ~596 (deuxième upload)
    sed -i '596s/contentType: '\''application\/json'\'',/contentType: false,/' "$MEDIA_GALLERY"
    
    echo "  ✓ Corrigé: $MEDIA_GALLERY (avec exceptions FormData)"
else
    echo -e "  ${RED}✗ Fichier non trouvé: $MEDIA_GALLERY${NC}"
fi

# ==========================================
# PARTIE 3: Recompilation
# ==========================================

echo -e "\n${YELLOW}[4/5] Recompilation des fichiers JavaScript...${NC}"

# Recompiler Digirisk
echo "  → Compilation de Digirisk..."
cd digiriskdolibarr
if [ -f "package.json" ]; then
    npm install --silent > /dev/null 2>&1
    npx gulp js_backend 2>&1 | grep -E "Finished|error" || true
    echo "  ✓ digiriskdolibarr.min.js généré"
else
    echo -e "  ${RED}✗ package.json non trouvé dans digiriskdolibarr${NC}"
fi
cd ..

# Recompiler Saturne
echo "  → Compilation de Saturne..."
cd saturne
if [ -f "package.json" ]; then
    npm install --silent > /dev/null 2>&1
    npx gulp js_backend 2>&1 | grep -E "Finished|error" || true
    echo "  ✓ saturne.min.js généré"
else
    echo -e "  ${RED}✗ package.json non trouvé dans saturne${NC}"
fi
cd ..

# ==========================================
# PARTIE 4: Vérification
# ==========================================

echo -e "\n${YELLOW}[5/5] Vérification des corrections...${NC}"

# Compter les occurrences de application/json
DIGIRISK_COUNT=$(grep -ro "application/json" digiriskdolibarr/js/digiriskdolibarr.min.js 2>/dev/null | wc -l || echo "0")
SATURNE_COUNT=$(grep -ro "application/json" saturne/js/saturne.min.js 2>/dev/null | wc -l || echo "0")

echo "  ✓ Digirisk: $DIGIRISK_COUNT occurrences de 'application/json'"
echo "  ✓ Saturne: $SATURNE_COUNT occurrences de 'application/json'"

# ==========================================
# RÉSUMÉ
# ==========================================

echo -e "\n${GREEN}========================================${NC}"
echo -e "${GREEN}✓ Correction terminée avec succès !${NC}"
echo -e "${GREEN}========================================${NC}"

echo -e "\n${YELLOW}Prochaines étapes:${NC}"
echo "1. Uploadez les fichiers suivants sur votre serveur via FTP:"
echo "   → htdocs/custom/digiriskdolibarr/js/digiriskdolibarr.min.js"
echo "   → htdocs/custom/saturne/js/saturne.min.js"
echo ""
echo "2. Videz le cache de votre navigateur (Ctrl+Shift+Suppr)"
echo ""
echo "3. Testez les fonctionnalités suivantes:"
echo "   ✓ Ajout de risques"
echo "   ✓ Ajout de tâches"
echo "   ✓ Ajout d'évaluations"
echo "   ✓ Upload d'images"
echo ""
echo -e "${GREEN}Le bug ModSecurity devrait être résolu ! 🎉${NC}\n"

Utilisation du script

# 1. Téléchargez les modules sur votre machine locale
cd ~/Téléchargements/
mkdir digirisk-fix && cd digirisk-fix

# Téléchargez depuis votre serveur FTP ou GitHub:
# - digiriskdolibarr/
# - saturne/

# 2. Rendez le script exécutable
chmod +x fix-modsecurity-bug.sh

# 3. Exécutez le script
./fix-modsecurity-bug.sh

# 4. Uploadez les fichiers .min.js générés sur votre serveur
- saturne.min.js
- digiriskdolibarr.min.js

Environment Version

21.1.0

Environment OS

serveur linux

Environment Web server

lamp

Environment PHP

8.3

Environment Database

mysql 8.4

Metadata

Metadata

Assignees

Labels

5BugSomething isn't working

Type

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions