10 KiB
10 KiB
Revue de code complète — Office Translator
Date : Mars 2026
Périmètre : Backend FastAPI (Python) + Frontend Next.js (TypeScript/React)
Méthode : Exploration du codebase, recherche bonnes pratiques 2025, audits pip-audit / npm audit, analyse ciblée frontend.
1. Synthèse exécutive
| Priorité | Thème | Impact |
|---|---|---|
| Critique | Path traversal sur /download/{filename} et /cleanup/{filename} |
Lecture/suppression de fichiers hors répertoire |
| Critique | Vulnérabilités connues (pip + npm) | RCE, DoS, fuites (Next.js, Starlette, Pillow, etc.) |
| Haute | Pas de normalisation session_id / chemins dans legacy extract/reconstruct |
Risque d’accès à des fichiers non prévus |
| Haute | Token JWT en localStorage sans refresh |
Expiration = déconnexion brute ; risque XSS |
| Haute | CORS * si CORS_ORIGINS vide |
En prod, exposition à toutes origines |
| Moyenne | Config dispersée (os.getenv partout) |
Erreurs de config, pas de validation au démarrage |
| Moyenne | Jobs de traduction en mémoire | Pas de partage entre workers (scale horizontal) |
| Moyenne | Duplication API_BASE / fetch+token côté frontend | Maintenance et incohérences |
2. Architecture (rapport agent)
- Backend :
main.py→ CORS, middlewares (rate limit, security, error, cleanup), router unique/api/v1(translate, auth, admin, api-keys, legacy, glossary, prompt). - Auth : JWT (access 15 min, refresh 7 j), blocklist JTI (Redis/mémoire), admin par token opaque (Redis/mémoire), API Key (X-API-Key, Pro).
- Traduction : POST
/translate→ validation fichier/URL → jobtr_*→asyncio.to_thread+ excel/word/pptx_translator + provider (OpenRouter, etc.) ; clés/modèles depuis admin settings + env. - Fichiers : Upload avec nom unique ; download v1 par
job_id+ ownership ; legacy/download/{filename}et/cleanup/{filename}sans normalisation du chemin.
3. Sécurité
3.1 Path traversal (critique)
Fichiers : routes/legacy_routes.py
GET /api/v1/download/{filename}(L.299–311) :file_path = config.OUTPUT_DIR / filename. Sifilename = "../../../etc/passwd", le chemin peut sortir deOUTPUT_DIR.DELETE /api/v1/cleanup/{filename}(L.314–325) : même construction.
Recommandation :
- Normaliser :
safe_name = Path(filename).name(pas de..). - Résoudre :
resolved = (config.OUTPUT_DIR / safe_name).resolve(). - Vérifier :
resolved.is_relative_to(config.OUTPUT_DIR.resolve())(Python 3.9+) ou équivalent. - Sinon 400/404.
3.2 Session / extract-texts / reconstruct-document
session_id(UUID généré côté serveur) : utilisé poursession_{session_id}.jsonet chemins. Vérifier que toutsession_idreçu en form est bien un UUID strict.session_data["input_path"]: s’assurer que le chemin résolu reste sousUPLOAD_DIRavant toute lecture.
3.3 Authentification
- JWT : si
JWT_SECRET_KEYabsent, clé éphémère au démarrage → tous les tokens invalidés au redémarrage (log CRITICAL). À corriger en prod. - Admin :
ADMIN_PASSWORDen clair à éviter ; utiliser uniquementADMIN_PASSWORD_HASH(bcrypt) en production. - Frontend : token et refresh en
localStorage→ exposés au XSS. Bonnes pratiques 2025 : cookies HTTP-only pour le token (ou au minimum documenter le risque et privilégier des pages à faible exposition XSS).
3.4 CORS
main.py: siCORS_ORIGINSvide ou*,allowed_origins = ["*"]avec warning. En production, définir des origines explicites.
3.5 Stripe webhook
services/payment_service.py:stripe.Webhook.construct_event(payload, sig_header, STRIPE_WEBHOOK_SECRET)→ signature bien vérifiée. Rien à changer côté vérification.
3.6 SSRF / Webhook URL
- Translate :
download_from_urlet validation webhook limitent schéma, DNS et IP privées/loopback. Cohérent avec les bonnes pratiques.
4. Vulnérabilités connues (dépendances)
4.1 Backend (pip-audit)
| Package | Version | Problème | Correction |
|---|---|---|---|
| deep-translator | 1.11.4 | PYSEC-2022-252 | Mettre à jour |
| fastapi | 0.109.0 | PYSEC-2024-38 | 0.109.1+ |
| pillow | 10.2.0 | CVE-2024-28219 | 10.3.0+ |
| python-multipart | 0.0.9 | CVE-2024-53981, CVE-2026-24486 | 0.0.18+ / 0.0.22+ |
| starlette | 0.35.1 | CVE-2024-47874, CVE-2025-54121 | 0.40.0+ / 0.47.2+ |
Action : Exécuter pip-audit puis mettre à jour les paquets (tests de non-régression après mise à jour).
4.2 Frontend (npm audit)
| Package | Problème | Action |
|---|---|---|
| next | RCE (flight), DoS, exposition Server Actions, etc. | npm audit fix ou mise à jour ciblée (ex. next@16.1.6) |
| minimatch | ReDoS | npm audit fix |
| ajv | ReDoS ($data) | npm audit fix |
Action : npm audit puis npm audit fix (ou --force avec prudence et tests).
5. Fiabilité et bonnes pratiques
5.1 Gestion d’erreurs
- Middleware global + handlers dédiés (TranslationError, ValidationError, etc.) → correct.
- OpenRouter : retry 429 + levée d’exception en cas d’échec (plus de retour silencieux du texte original) → bon.
5.2 Configuration
- Config : tout en
os.getenv()dansconfig.pyet ailleurs. Risque : valeurs manquantes ou incohérentes au démarrage. - Recommandation : centraliser dans un module type Pydantic BaseSettings (validation, typage, valeurs par défaut) et charger une seule fois au démarrage.
5.3 Jobs de traduction
_translation_jobsen mémoire : en multi-workers (plusieurs processus uvicorn), les jobs ne sont pas partagés.- Recommandation : pour un scale horizontal, stocker l’état des jobs dans Redis (ou autre store partagé).
5.4 Legacy
/translate-batch,/download/{filename},/cleanup/{filename},/extract-texts,/reconstruct-document: peu ou pas d’auth, exposition de chemins/fichiers.- Recommandation : renforcer l’auth et la validation des paramètres, ou déprécier au profit des endpoints v1 (translate + download par
job_id).
6. Frontend (rapport agent)
6.1 Types et erreurs
any:app/(app)/ollama-setup/page.tsx(models, error),app/(app)/settings/subscription/page.tsx(PLAN_ICONS),app/pricing/page.tsx(PLAN_ICONS). Remplacer par des types précis.- Error boundary : aucun au niveau racine (
app/layout.tsx). Ajouter un ErrorBoundary pour éviter des écrans blancs.
6.2 Validation et timeout
- Login / Admin login : pas de validation explicite (email, mot de passe) avant submit.
- Translate : pas de validation centralisée de
file/config(taille, type, champs requis) avant l’appel API. - Fetch : plusieurs appels sans timeout (pricing, subscription, admin verify, settings, translate, polling, download). Ajouter
AbortController+ timeout (ex. 8–30 s selon l’endpoint).
6.3 Auth et stockage
- Token :
localStorage("token", "refresh_token", "user"). Risque XSS ; en production privilégier cookies HTTP-only si possible. - Refresh :
refresh_tokenstocké mais jamais utilisé ; aucun appel/auth/refresh. Quand l’access token expire, l’utilisateur est déconnecté. Implémenter un refresh automatique (intercepteur ou hook) pour améliorer l’UX.
6.4 Duplication et centralisation
- API_BASE : répété dans plusieurs fichiers (useTranslationSubmit, useTranslationConfig, TranslationComplete, settings/services, lib/api). Utiliser une seule source :
@/lib/configouapiClient. - Pattern fetch + token : répété partout. Utiliser systématiquement apiClient (déjà en place pour auth, glossaries, api-keys) pour tous les appels authentifiés.
- URL en dur :
app/(app)/ollama-setup/page.tsxL.85"http://localhost:8000/api/auth/settings"→ remplacer parAPI_BASE + "/api/v1/..."(et vérifier le chemin exact de l’API).
7. Plan d’action priorisé
Immédiat (sécurité)
- Path traversal : normaliser
filenameet vérifierresolved.is_relative_to(OUTPUT_DIR)danslegacy_routes.pypour/download/{filename}et/cleanup/{filename}. - Dépendances : mettre à jour FastAPI, Starlette, Pillow, python-multipart, deep-translator ; puis Next.js, minimatch, ajv (avec tests après chaque vague).
Court terme (sécurité / robustesse)
- Session / reconstruct : valider
session_id(UUID) et s’assurer que tout chemin dérivé reste sousUPLOAD_DIR. - CORS : en prod, définir
CORS_ORIGINSexplicitement (pas*). - Admin : en prod, n’utiliser que
ADMIN_PASSWORD_HASH(bcrypt). - Frontend : ajouter un ErrorBoundary racine et des timeouts sur les fetch critiques (translate, download, polling, auth verify).
Moyen terme (qualité / maintenabilité)
- Config : migrer vers Pydantic BaseSettings pour la config backend.
- Frontend : centraliser API_BASE et utiliser apiClient partout ; implémenter le refresh token.
- Jobs : si scale horizontal prévu, stocker l’état des jobs dans Redis (ou équivalent).
- Legacy : protéger ou déprécier les routes legacy (auth + validation des paramètres).
Long terme (bonnes pratiques)
- Auth frontend : étudier le passage à des cookies HTTP-only pour le token (avec adaptation du backend).
- Validation : validation explicite login/admin et validation centralisée des paramètres de traduction avant appel API.
- Types : supprimer les
anyet renforcer les types (discriminated unions, type predicates) côté TypeScript.
8. Références
- FastAPI & Next.js security (TurboStarter, Next.js Data Security, Mikul Gohil).
- Python code review (DeepSource, Kodus, Medium).
- TypeScript security & quality (Krython, Kodus).
- Exploration et revue frontend par agents (explore + generalPurpose) sur le dépôt.
Document généré dans le cadre d’une revue de code complète. Aucune modification n’a été appliquée automatiquement ; les changements sont à planifier et à tester.