Aller au contenu principal

Sécurité de la plateforme

Recrut'Auto applique une stratégie defense in depth sur 5 couches indépendantes, du firewall périmétrique jusqu'à la validation applicative. Cette page récapitule les protections que vos intégrations (API REST, MCP, plugin LinkedIn) traversent et les garanties que vous pouvez attendre.

Couche 1 — Edge & IP intelligence

À la frontière de notre infrastructure, nous filtrons les IPs malveillantes connues avant tout traitement applicatif :

  • CrowdSec Community Blocklist (~15 000 IPs auto-mises à jour) — scanners Shodan/Censys, bots de brute-force SSH, IPs identifiées par la communauté open-source CrowdSec sur l'ensemble des Security Engines connectés.
  • Détection comportementale — scenarios http-bf, http-crawl-non_statics, http-probing, http-bad-user-agent analysent les logs en continu et bannissent automatiquement les IPs déclenchant des patterns d'attaque.
  • Drop kernel-level au firewall périmétrique : les IPs bannies sont rejetées avant même d'atteindre le load balancer applicatif. Latence de réaction : ~10 secondes entre détection et bannissement effectif.

Couche 2 — TLS & rate-limiting

Toutes les communications externes utilisent TLS 1.2+ avec des certificats Let's Encrypt automatiquement renouvelés. Les certificats internes sont émis via le challenge DNS-01, sans exposer aucun service interne sur Internet.

Côté rate-limit, vous êtes plafonné par défaut à :

SurfaceLimite
API REST /api/* (Bearer token)60 r/min par utilisateur
Surface admin20 r/s
Endpoints publics (booking)10 r/s
MCP (Bearer PAT)30 r/s
Tunnel Sentry30 r/s

Au-delà, vous recevez un 429 Too Many Requests. Implémentez un backoff exponentiel.

Couche 3 — Auth & ownership

Tous les endpoints /api/* (sauf opt-in publics explicites comme /api/calendars/public/*) exigent un des modes d'authentification suivants :

  • Bearer JWT Keycloak (utilisateur connecté côté front, OIDC PKCE).
  • Personal Access Token (Authorization: Bearer ra_<token>, voir Tokens).
  • Token signé HS256 scopé (booking public 14 jours, image candidat 10 minutes).

Une fois authentifié, chaque requête est filtrée par ownership de souscription : vous ne voyez que les ressources de votre abonnement, jamais celles d'un autre tenant. Cette règle est appliquée au niveau de chaque service backend (get_subscription(db, current_user)), pas seulement au niveau de la base.

Les endpoints sensibles non-utilisateur (analyse de réponses LinkedIn par notre moteur ML, etc.) sont protégés par des tokens internes statiques rotables, jamais exposés au navigateur ni au plugin.

Couche 4 — Validation applicative

  • Body cap — les requêtes sont rejetées avec 413 Payload Too Large au-delà de :
    • 10 MiB sur le tronc commun /api/*
    • 4 KiB sur les feature-flags
    • 50 MiB sur l'import CV
  • Transfer-Encoding sanity — les requêtes avec un header Transfer-Encoding malformé sont rejetées avec 400 (mitigation request-smuggling).
  • Pydantic v2 strict mode sur les schémas critiques (extra=forbid + max_length + pattern regex sur les IDs/slugs). Un payload contenant un champ inattendu est rejeté avec 422.
  • MIME validation sur les uploads (CV PDF, enregistrements audio d'entretien) — vérifié via python-magic, pas via le content-type déclaré par le client.
  • Scan antivirus ClamAV sur tous les uploads recruteurs (POST /api/import/cv, POST /api/import/csv, POST /api/interview/meets/{id}/recording). Politique fail-closed : si le daemon clamd est injoignable, l'upload est rejeté avec 503 antivirus_unavailable plutôt que de risquer un fichier non scanné. Une menace détectée renvoie 422 ; le nom de signature ClamAV est loggé en interne mais jamais retourné au client pour éviter qu'un attaquant itère pour trouver le bypass. Les admins disposent d'une page /security pour tester le daemon (carte status, scan d'un fichier de test, bouton EICAR).

Couche 5 — Données privées & assets

Les images de profil candidat (GET /api/candidates/{id}/image) sont servies via un mécanisme d'URL signée courte durée :

  1. Votre application appelle GET /api/candidates/{id}/image-url avec un Bearer token.
  2. Le backend valide l'ownership et retourne un JWT HS256 audience-scopé, valide 10 minutes.
  3. La balise <img src=...?token=JWT> est consommée par le navigateur sans réauthentification.

Cela permet d'authentifier l'asset sans exposer le Bearer token dans une requête <img>. Les enregistrements d'entretien (S3) suivent le même pattern avec des URLs présignées.

Audit logging

Tous les events sécurité (auth gate hit, body cap dépassé, signature invalide, IP whitelist match) sont émis sur le logger structuré recrutauto.security et collectés dans Loki. Les anomalies (taux d'anonymous_warning anormal, par exemple) sont alertées via Sentry.

Codes d'erreur courants

CodeSignification
400Requête malformée (Transfer-Encoding suspect, JSON invalide)
401Token absent, expiré ou invalide
402Aucun abonnement actif — souscrivez un plan
403Permissions insuffisantes ou IP bannie au niveau périmètre
404Ressource introuvable ou hors de votre périmètre d'abonnement
413Body trop gros
422Validation Pydantic échouée (champ inconnu, type invalide, longueur dépassée)
429Rate limit dépassé

Bonnes pratiques d'intégration

  • Stockez les Personal Access Tokens dans un coffre (HashiCorp Vault, AWS Secrets Manager, etc.), jamais en clair dans le code.
  • Rotation : générez un nouveau token tous les 90 jours et révoquez l'ancien après bascule.
  • Scopez minimal : si votre intégration ne lit que les campagnes, évitez d'utiliser un token admin.
  • Soyez rapides à back-off sur 429 — un client poli évite d'être confondu avec un scraper et d'être banni au niveau perimeter.
  • Vérifiez le certificat TLS côté client. Aucun endpoint Recrut'Auto ne devrait être appelé en HTTP non chiffré.

Reporter une vulnérabilité

Si vous découvrez une faille de sécurité, contactez security@recrutauto.fr (clé PGP disponible sur demande). Nous nous engageons à accuser réception sous 24h ouvrées et à coordonner un disclosure responsable.

astuce

Cette page décrit le comportement observable depuis vos intégrations. L'architecture interne complète (composants, runbooks ops) est documentée séparément à destination des équipes RecrutAuto.