Un formulaire de contact ou une API publique sans contrôle, c’est comme un immeuble sans portier : n’importe qui entre, laisse des déchets ou force la porte. Le spam, la force brute et le scraping ne sont pas un « bruit mineur » : ils saturent les boîtes mail, consomment le quota d’email et peuvent faire tomber un endpoint un vendredi après-midi.
Cet article explique une approche en couches — le même schéma que ce portfolio utilise en production avec Astro, applicable à Laravel et Node — pour qu’une personne non technique comprenne le pourquoi, et qu’un technicien ait checklist, ordre des contrôles et erreurs à éviter.
Pourquoi c’est important pour le business
Chaque faux lead coûte du temps commercial. Chaque tentative de login sans limite est une loterie contre des identifiants fuités. Chaque webhook ou endpoint « ouvert » est une surface d’abus. Protéger n’est pas de la paranoïa : c’est garder le canal utile aux humains réels et coûteux pour les bots.
- Boîte mail utilisable : moins de spam = plus de réponses aux vrais clients.
- Disponibilité : le rate limit évite qu’un script fasse tomber le serveur.
- Confiance : valider côté serveur réduit les déchets CRM et tickets inventés.
- Conformité pratique : moins de PII d’attaquants dans logs et bases.
Concepts clés (simple + technique)
Le portier en couches
Aucune couche seule ne suffit. Le honeypot attrape les bots maladroits ; le rate limit freine le volume ; le timing détecte les envois inhumains ; validation et sanitisation soignent ce qui entre ; Turnstile ajoute de la friction seulement si besoin. Comme un immeuble : réception, caméra, clé et alarme — pas seulement un panneau « interdit ».
| Couche | Ce qu’elle bloque | Réponse typique |
|---|---|---|
| Rate limiting | Volume / force brute | 429 + Retry-After |
| Honeypot | Bots qui remplissent tout | 200 silencieux (sans traiter) |
| Form timing | Envois < ~3.5s | 400 |
| Origin check | Scripts cross-origin basiques | 403 |
| Turnstile | Bots plus sophistiqués | 400 si token invalide |
| Zod + sanitiser | Déchets et payloads bizarres | 400 avec erreurs de champ |
Rate limiting
Limite les requêtes par IP (et par utilisateur si applicable) sur une fenêtre de temps. En mémoire suffit pour un seul processus ; avec plusieurs réplicas il faut Redis ou un autre store partagé. Exemples indicatifs : login 5/min, reset password 3/heure, contact 5/min.
Honeypot et timing
Le honeypot est un champ caché (display: none ou hors écran) que les humains ne voient pas. S’il arrive rempli, refusez en silence (200 sans traiter) pour ne pas former le bot. Le timing stocke un timestamp au rendu et refuse les envois plus rapides qu’un humain raisonnable.
Validation, sanitisation et origine
La validation front améliore l’UX ; celle du serveur est celle qui compte. Schémas (Zod ou équivalent), strip HTML sur le texte brut, longueurs max, et en production vérifier Origin/Referer. Pas infaillible, mais ça filtre beaucoup de bruit bon marché.
Guide pratique : flux dans un endpoint
- Rate limit check →
429si dépassé. - Honeypot check →
200silencieux si le champ caché a une valeur. - Form timing check →
400si trop rapide. - Origin check →
403si l’origine n’est pas celle du site. - Turnstile (si configuré) →
400si le token échoue. - Validation par schéma →
400avec erreurs de champ. - Sanitisation → traiter (email, CRM, file).
Un honeypot bien fait
- Caché en CSS, pas avec un
type="hidden"trop évident si vous pouvez l’éviter. - Nom trompeur (
website,company_url) — pashoneypot. tabindex="-1"etautocomplete="off"; ne doit pas être accessible par accident aux lecteurs d’écran.- Si rempli : répondre succès faux, pas un
403explicite.
Cloudflare Turnstile
Quand le volume de spam justifie une friction supplémentaire, Turnstile est léger et plus respectueux de la vie privée que des alternatives agressives. TURNSTILE_SITE_KEY côté client ; TURNSTILE_SECRET_KEY uniquement côté serveur. Le serveur vérifie le token avant de traiter.
Erreurs fréquentes
- Se fier uniquement à la validation frontend.
- Rate limit seulement sur le login, pas sur le contact ni les endpoints publics.
- Honeypot visible, avec un vrai label, ou focusable clavier/lecteurs.
- Répondre
403au honeypot (le bot apprend et s’adapte). - Logger des payloads complets avec emails et téléphones (PII dans les logs).
- Rate limit en mémoire avec 3 réplicas (chacune a son compteur).
- Messages d’erreur qui révèlent si un email « existe » dans le système.
Checklist de protection
- Inventaire des endpoints publics sensibles (login, contact, reset, webhooks).
- Rate limit avec seuils documentés et
Retry-After. - Honeypot + timing sur les formulaires HTML.
- Contrôle Origin/Referer en production.
- Schéma de validation serveur + sanitisation.
- Turnstile optionnel quand le spam le justifie.
- Store partagé (Redis) s’il y a plus d’une réplica.
- Logs sans PII inutile ; métriques 429/400 pour détecter les attaques.
Cela se connecte à audit de sécurité, cybersécurité et APIs REST .