From 94fa9de6a76f43e67e26b03e26e98a49d8fc791e Mon Sep 17 00:00:00 2001 From: Xor290 Date: Sun, 17 May 2026 14:13:38 +0200 Subject: [PATCH] fix(security): SSRF log injection and folder permissions --- backend/gestion/handlers/product.go | 4 ++-- backend/gestion/handlers/settings.go | 3 ++- backend/gestion/services/geo_services.go | 22 +++++++++++++++++----- backend/gestion/services/tomtom.go | 22 +++++++++++++++++----- backend/gestion/workers/redis_worker.go | 4 +++- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/backend/gestion/handlers/product.go b/backend/gestion/handlers/product.go index a66d8c5b..40d4c75b 100644 --- a/backend/gestion/handlers/product.go +++ b/backend/gestion/handlers/product.go @@ -384,7 +384,7 @@ func CreateProduct(c *gin.Context) { // ✅ CRÉER LE DOSSIER DE MANIÈRE SÉCURISÉE destFolder := filepath.Join("uploads", mediaType+"s") - if err := os.MkdirAll(destFolder, 0755); err != nil { + if err := os.MkdirAll(destFolder, 0750); err != nil { log.Printf("❌ [CreateProduct] Erreur création dossier: %v", err) rollbackFiles(savedFiles) database.DeleteProduct(product.ID) @@ -848,7 +848,7 @@ func UploadMedia(c *gin.Context) { // ✅ CRÉER LE DOSSIER destFolder := filepath.Join("uploads", fileType+"s") - if err := os.MkdirAll(destFolder, 0755); err != nil { + if err := os.MkdirAll(destFolder, 0750); err != nil { log.Printf("❌ [UploadMedia] Erreur création dossier: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur création dossier"}) return diff --git a/backend/gestion/handlers/settings.go b/backend/gestion/handlers/settings.go index bd7c50d6..01268f9f 100644 --- a/backend/gestion/handlers/settings.go +++ b/backend/gestion/handlers/settings.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "os" + "strings" "github.com/gin-gonic/gin" ) @@ -89,7 +90,7 @@ func UpdateSettings(c *gin.Context) { if err := services.TelegramBot.SetWebhook(webhookURL); err != nil { log.Printf("⚠️ [SETTINGS] Erreur enregistrement webhook Telegram: %v", err) } else { - log.Printf("✅ [SETTINGS] Webhook Telegram enregistré: %s", webhookURL) + log.Printf("✅ [SETTINGS] Webhook Telegram enregistré: %s", strings.NewReplacer("\n", "", "\r", "").Replace(webhookURL)) } } } diff --git a/backend/gestion/services/geo_services.go b/backend/gestion/services/geo_services.go index 22d1e028..4f5708d6 100644 --- a/backend/gestion/services/geo_services.go +++ b/backend/gestion/services/geo_services.go @@ -274,13 +274,25 @@ func CalculateETAWithTomTom(from, to Coordinates) (int, float64, error) { } // API TomTom Routing: Calculate Route avec trafic - apiURL := fmt.Sprintf( - "https://api.tomtom.com/routing/1/calculateRoute/%f,%f:%f,%f/json?key=%s&traffic=true&travelMode=car", - from.Latitude, from.Longitude, to.Latitude, to.Longitude, apiKey, - ) + u := &url.URL{ + Scheme: "https", + Host: "api.tomtom.com", + Path: fmt.Sprintf("/routing/1/calculateRoute/%f,%f:%f,%f/json", from.Latitude, from.Longitude, to.Latitude, to.Longitude), + } + q := url.Values{} + q.Set("key", apiKey) + q.Set("traffic", "true") + q.Set("travelMode", "car") + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + distance := CalculateDistance(from, to) + return CalculateETA(distance), distance, nil + } client := &http.Client{Timeout: 8 * time.Second} - resp, err := client.Get(apiURL) + resp, err := client.Do(req) if err != nil { // Fallback sur calcul local en cas d'erreur réseau distance := CalculateDistance(from, to) diff --git a/backend/gestion/services/tomtom.go b/backend/gestion/services/tomtom.go index 912ccc5c..7b970cd2 100644 --- a/backend/gestion/services/tomtom.go +++ b/backend/gestion/services/tomtom.go @@ -11,6 +11,7 @@ import ( "io" "log" "net/http" + "net/url" "os" "time" ) @@ -21,13 +22,24 @@ func GetETAWithTraffic(from, to Coordinates) (etaMinutes int, distanceKm float64 return 0, 0, fmt.Errorf("TOMTOM_API_KEY non configurée") } - url := fmt.Sprintf( - "https://api.tomtom.com/routing/1/calculateRoute/%f,%f:%f,%f/json?key=%s&traffic=true&travelMode=car", - from.Latitude, from.Longitude, to.Latitude, to.Longitude, apiKey, - ) + u := &url.URL{ + Scheme: "https", + Host: "api.tomtom.com", + Path: fmt.Sprintf("/routing/1/calculateRoute/%f,%f:%f,%f/json", from.Latitude, from.Longitude, to.Latitude, to.Longitude), + } + q := url.Values{} + q.Set("key", apiKey) + q.Set("traffic", "true") + q.Set("travelMode", "car") + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + return 0, 0, fmt.Errorf("erreur construction requête TomTom: %w", err) + } client := &http.Client{Timeout: 10 * time.Second} - resp, err := client.Get(url) + resp, err := client.Do(req) if err != nil { return 0, 0, fmt.Errorf("erreur requête TomTom: %w", err) } diff --git a/backend/gestion/workers/redis_worker.go b/backend/gestion/workers/redis_worker.go index 0a42b3b3..26ac29e7 100644 --- a/backend/gestion/workers/redis_worker.go +++ b/backend/gestion/workers/redis_worker.go @@ -68,7 +68,9 @@ func AutoAssignWorker(database *db.Database) { nextCommand.CommandID, err) } else { log.Printf("✅ Commande %d auto-assignée", nextCommand.CommandID) - database.RemoveCommandFromQueue(nextCommand.CommandID) + if err := database.RemoveCommandFromQueue(nextCommand.CommandID); err != nil { + log.Printf("⚠️ Impossible de retirer la commande %d de la queue: %v", nextCommand.CommandID, err) + } } } }