Guides Tech

RGPD pour les développeurs : coder la confiance avant tout.

Dans cet article, on va parler du RGPD pour les développeurs.
C’est un sujet que je connais bien : j’ai rencontré la police des données personnelles bien avant de créer WeLoveDevs.

“Bonjour, c’est la CNIL. Levez les mains des claviers s’il vous plaît.”
La personne venait d’entrer sur notre plateau haussmannien. Elle a sorti un badge avec une plaque. On se serait cru dans Les Experts. Sauf qu’on n’était pas à Miami, mais à Paris.
Le CTO a ouvert MySQL Workbench et lui a confié son PC. On est tous partis prendre l’air pendant l’inspection.

Cette scène, je ne l’ai jamais oubliée. Elle m’a appris une chose : la confidentialité, ce n’est pas qu’une règle, c’est une culture.

En réalité, le RGPD, c’est une bonne nouvelle. Il simplifie la vie : on passe plus de temps à sécuriser qu’à remplir des formulaires CNIL.

Chez WeLoveDevs, la privacy fait partie de l’ADN depuis le début.
On existait avant le RGPD, et on a toujours mis la protection des données au premier plan, parce que la confiance se construit dès le premier cookie, dès le formulaire d’inscription.

Voici donc les cinq règles que je voudrais que tous les développeurs connaissent à propos du RGPD.
Et dans un second temps, on fera quelques cas pratiques.

Les 5 Règles du RGPD pour les développeurs.

1 – Les données personnelles, tu reconnaîtras.

Avant même de commencer à intégrer une maquette, tu peux déjà repérer les données personnelles.
Prenons une page qui présente un recruteur sur WeLoveDevs : on y voit sa photo, son nom, son prénom, son poste.
Ces informations sont publiques, oui, mais elles restent personnelles.

Règle de base : les données personnelles d’un utilisateur lui appartiennent.

Il peut, à tout moment :

  • retirer son consentement ;
  • demander la suppression de ses données ;
  • en demander un export ;
  • ou les modifier.

Et ça doit être facile. Un bouton permet de le faire.
Mais même si la demande arrive par e-mail, il n’y a qu’une seule réponse correcte : “C’est fait !”

Le RGPD distingue deux grands types de données :

  • Les données personnelles, qui identifient directement ou indirectement une personne (nom, e-mail, IP, cookie…).

  • Les données dites “sensibles”, qui révèlent des éléments comme la santé, les origines, les opinions ou la vie sexuelle.
    Ces dernières font partie du RGPD, mais elles bénéficient d’un régime de protection renforcé.

Le grand piège ? Une note CRM, un commentaire sur le profil d’un utilisateur, tout ça lui appartient. Donc par exemple la personne du support qui écrit “Le client est désagréable” dans le CRM. Et bien ça appartient au dit client. Il peut demander un export et il le lira.

2 – Privacy by design, tu penseras.

“Privacy by design”, c’est pas une case à cocher, c’est un réflexe. Ça veut dire arrêter de semer des données personnelles partout.

Beaucoup d’équipes stockent “par précaution” : on garde tout, au cas où. Mauvaise idée.

Le pattern “Single Source of Truth” s’applique aussi à la privacy. Ta base applicative n’est pas la seule source : les données partent dans le CRM, dans l’outil marketing, dans les logs, les exports, les notifications Slack.

Et quand tu devras faire une routine RGPD, tu devras tout nettoyer. Pas juste la base. Alors prends l’habitude de limiter les copies, les dumps et les logs.

Quand un projet traite des données sensibles, suit un grand nombre d’utilisateurs ou croise plusieurs sources d’informations, il doit passer par une AIPD : une analyse d’impact sur la protection des données.

Ce n’est pas de la paperasse, c’est de l’hygiène. Les données personnelles s’infiltrent partout.

Quelques exemples “vu en production” :

  • une notification Slack avec l’e-mail de l’utilisateur fraîchement créé ;
  • un rapport envoyé par e-mail avec les noms des utilisateurs actifs du jour ;
  • un export CSV de newsletter oublié dans le dossier “Téléchargements” ;
  • un dump SQL datant d’une migration de base de données, toujours présent dans ~/dev ;
  • un log contenant un ID et une IP utilisateur stocké sur le serveur ou dans GCP Cloud Logging.

3 – C’est pas Hodor, c’est IDOR !

Limiter les accès est tout aussi important.
Une des principales vulnérabilités listées par l’OWASP s’appelle Insecure Direct Object Reference (IDOR).
En clair, c’est quand un utilisateur peut accéder à une ressource qui ne lui appartient pas, simplement en modifiant une URL.

OWASP Top 10 est un référentiel de 10 grandes familles de vulnérabilités web dont IDOR. On vous fait un article sur le sujet bientôt !

Quand j’étais en école d’ingénieur, le CMS de cours affichait un agenda en ligne.
L’URL ressemblait à ceci : isen.cms.fr/agenda/p54050, où p54050 était mon identifiant, aussi utilisé comme numéro d’étudiant.
C’était une information publique, visible sur les listes d’examen.

Il suffisait donc de visiter isen.cms.fr/agenda/p54151 pour afficher l’agenda d’un autre étudiant.
Pas besoin d’être un hacker. Si vous cherchiez Mew, vous pouviez savoir qu’il était en cours d’anglais et dans quelle salle, avec quel prof. 

C’est pratique pour trouver un moment pour travailler sur le projet en commun pour le cours de SGBD. C’est pas cool si c’est votre ex-toxique qui vous stalk.

La prévention est simple :

  • dès la base de données, vérifiez que chaque donnée est liée à l’utilisateur légitime ;
  • ou utilisez les fonctionnalités de votre framework pour gérer les permissions.

C’est une mesure de base, mais elle est indispensable.

4 – Pour une finalité éclairée, tu peux collecter des données.

Quand on développe un formulaire d’inscription, il y a souvent un “bloc RGPD” dans la spec. Parfois, cette même spec précise que la case de consentement doit être cochée par défaut. C’est exactement pour ce genre de situation qu’il faut connaître les bases, parce qu’il arrive qu’on nous demande, sans le savoir, de faire quelque chose d’illégal.

Lorsque l’utilisateur donne ses données, il doit le faire de manière éclairée. Il doit savoir à quelle fin elles sont collectées et comment elles seront utilisées. Sur WeLoveDevs, par exemple, vous remplissez votre profil pour accéder à des opportunités professionnelles : c’est clair, explicite et lié à la mission du site.

Une finalité doit être légitime, limitée et éclairée.
Légitime : Uber Eats n’a pas de raison de collecter ton salaire pour t’aider à trouver un emploi.
Limitée : on précise dès le départ combien de temps les données sont conservées et quand elles sont supprimées. Dans un CRM, c’est souvent trois ans après le dernier contact ; dans un outil de recrutement, six mois à deux ans selon les postes.
Éclairée : si la case “Je consens à…” est précochée, l’utilisateur n’a pas donné son accord en toute connaissance de cause.

Et c’est ce que la CNIL regarde en premier. 

5 – À partir de quel moment on a un DPO ?

Le DPO (Délégué à la Protection des Données) devient obligatoire dans trois cas : pour les organismes publics, pour les entreprises qui suivent ou profilent des utilisateurs à grande échelle, et pour celles qui traitent massivement des données sensibles.

Son rôle, c’est de documenter la conformité et de piloter les obligations légales : registre des activités de traitement, analyses d’impact (AIPD), et communication avec la CNIL. C’est la personne à qui les utilisateurs ou les autorités peuvent s’adresser.

Le développeur, lui, met ces obligations en pratique. C’est son code qui chiffre les mots de passe, purge les données, ou anonymise les logs. Il n’a pas besoin d’être juriste, mais il doit comprendre les règles que le DPO formalise. Les deux travaillent sur le même objectif : un produit conforme et digne de confiance.

La conformité, ce n’est pas qu’un dossier administratif. C’est une culture commune entre le DPO et l’équipe tech.

Le RGPD pour les développeurs en pratique.

On a pu comprendre déjà que le RGPD pour les développeurs c’est pas juste de la paperasse, c’est une hygiène au quotidien. Mais entre la théorie et la prod, il y a toujours un fossé.
Je te propose 4 situations, 4 cas pratiques pour agir dès demain.

Cas pratique 1 : Le script “Third-party” mal placé

Un exemple simple.
Tu suis le tutoriel Stripe et tu ajoutes, dans ton HTML:

<script src="https://js.stripe.com/v3/"></script>

Problème: c’est un script third party.
Dès qu’il est dans le layout global, le visiteur qui vient juste lire un article de blog le charge aussi.
Tu élargis inutilement la surface d’exposition et tu rends le consentement inopérant.

Idéalement, tu obtiens un consentement explicite avant d’injecter le script, ou tu déclenches le chargement via un bouton clair du type “Passer au paiement”.

Implémentation simple : injection conditionnelle.

<!-- layout global -->
<head>
  <script>
    function loadStripe() {
      // Ne rien charger si l'utilisateur n'a pas accepté la finalité "payment"
      if (window.myCMP?.hasConsent?.('payment') !== true) return;
      if (document.querySelector('script[data-src="stripe-v3"]')) return; // déjà chargé
      var s = document.createElement('script');
      s.setAttribute('data-src', 'stripe-v3');
      s.src = 'https://js.stripe.com/v3/';
      s.async = true;
      document.head.appendChild(s);
    }

    // Cas 1: l'utilisateur a déjà donné son accord avant d'arriver sur la page
    document.addEventListener('DOMContentLoaded', loadStripe);


    // Cas 2: l'utilisateur accepte dans la bannière
    window.addEventListener('cmp:consent:update', function (e) {
      if (e?.detail?.categories?.includes('payment')) loadStripe();

    });
  </script>
</head>

À retenir :

  • Un script tiers ne doit apparaître que là où la finalité s’exécute.
  • La bannière de consentement doit contrôler l’injection de la balise <script>, pas juste afficher un message.
  • Page dédiée, consentement vérifié, injection tardive: simple, propre, conforme.

Cas pratique 2 : L’utilisateur veut supprimer ses données.

Oui, c’est un classique aussi. Ils font ça tous les jours !

Le problème c’est quoi ? C’est qu’on doit pouvoir prouver qu’on a bien supprimé les données.
Mais on doit pas les garder.

Par exemple si l’utilisateur marcel@welovedevs.com veut supprimer son compte. Je lance le script qui va supprimer ses données partout. 

// deletionRoutine.js (minimal)

// imports de modules

function startDeletionRoutine(email, userId) {
  const rid = id();                 // identifiant de procédure à renvoyer à l'utilisateur
  const hmac = sig(email, rid);     // preuve non réversible (ne pas stocker l'email)

  dbInsert({ request_id: rid, requester_hmac: hmac, status: 'pending', created_at: Date.now() });
  dbUpdate({ request_id: rid, status: 'in_progress', last_update: Date.now() });

  const jobs = [ delMailchimp(email) ];
  if (userId) jobs.push(delCRM(userId), delStorage(userId));

  Promise.allSettled(jobs).then(results => {
    const audit = {
      mailchimp: results[0].status,
      crm:      userId ? results[1].status : 'skipped',
      storage:  userId ? results[2].status : 'skipped',
      at: new Date().toISOString()
    };
    const ok = results.every(r => r.status === 'fulfilled');

    dbUpdate({
      request_id: rid,
      status: ok ? 'done' : 'error',
      audit_log: JSON.stringify(audit),
      last_update: Date.now()
    });
  });

  return rid; // à communiquer à l'utilisateur comme preuve de procédure
}

module.exports = { startDeletionRoutine };

Mais après si Marcel me demande de confirmer, je fais quoi ? Il faut garder un hash, salé si possible, de sa demande. Par exemple : hasher son email avec un identifiant de demande et lui renvoyer cet identifiant pour confirmer la procédure.

Comme ça, s’il me demande de vérifier l’état de la procédure, je prend son email, son identifiant de procédure, je le hash et je ressort l’ensemble des éléments.

// libs/secure.js
const crypto = require('crypto');

const SERVER_SECRET = process.env.DELETION_SECRET; // stocké dans un secret manager

function makeRequestId() {
  return crypto.randomUUID();
}

function requesterHmac(email, requestId) {
  return crypto
    .createHmac('sha256', SERVER_SECRET)
    .update(`${email}|${requestId}`)
    .digest('hex');
}

module.exports = { makeRequestId, requesterHmac };

Et on envoie un email de réponse : “Votre demande de suppression a été enregistrée (3fa85f64-5717-4562-b3fc-2c963f66afa6)”

Cas pratique 3 : Anonymiser les données, correctement.

Le problème c’est que notre Chief Product Officier a demandé à ce que les données soient anonymisées. Il ne veut pas perdre toutes les statistiques !

On va donc supprimer le prénom et le nom de l’utilisateur, son mail, son numéro de téléphone.
Et garder toutes les données dans un document avec un nouvel id ou dans une base séparée.

Toutefois, l’anonymisation doit être solide. Par exemple, avec un profil de développeur iOS freelance depuis quinze ans à Lille, on peut, grâce à l’OSINT, le retrouver facilement. Donc, il faut réduire les signaux uniques.

Si on hache les données, il faut que ce soit irréversible. Et que la granularité soit assez large. On ne peut pas tout garder et notre CPO préféré va devoir faire des choix.

Cas pratique 4 : une conversation entre utilisateurs.

Imagine qu’un recruteur ait échangé avec un développeur sur WeLoveDevs. Le candidat a trouvé un poste et décide de supprimer son compte.

Si on efface les données brutalement, l’interface du recruteur, qui est peut-être encore en train de lui parler, risque de planter.
Il faut donc caviarder les messages et les documents auxquels le recruteur a encore accès. Le contenu généré par l’utilisateur doit être supprimé, mais pas forcément l’enveloppe de la conversation.

L’idée, c’est de préserver la cohérence de l’application tout en respectant la demande de suppression.
On anonymise l’auteur, on vide le message, on garde juste la structure.

// redactUserMessages.js
// Appelé après la routine RGPD pour les développeurs principale
// Objectif : anonymiser les traces dans les conversations sans casser l'UI

function redactUserMessages(userId) {
  console.log(`Caviardage des messages pour l'utilisateur ${userId}...`);

  // 1. Marquer les messages envoyés par l'utilisateur
  db.query(`
    UPDATE messages
    SET 
      content = '[message supprimé à la demande de l’utilisateur]',
      author_id = NULL,
      is_redacted = TRUE
    WHERE author_id = $1
  `, [userId]);

  // 2. Supprimer les fichiers ou pièces jointes associés
  db.query(`
    UPDATE attachments
    SET 
      file_path = NULL,
      file_status = 'deleted'
    WHERE uploader_id = $1
  `, [userId]);

  // 3. Anonymiser le profil dans les threads
  db.query(`
    UPDATE threads
    SET 
      last_author_name = 'Utilisateur supprimé',
      last_author_id = NULL
    WHERE last_author_id = $1
  `, [userId]);

  console.log(`Caviardage terminé pour ${userId}.`);
}

Partie 3 – Risques et sanctions.

Sanctions financières.

Le RGPD prévoit des amendes pouvant atteindre 20 millions d’euros ou 4 % du chiffre d’affaires annuel mondial, selon la gravité du manquement.

En 2024, la CNIL a prononcé 87 sanctions pour un total de 55,2 M€, avec une montée en puissance de la procédure simplifiée (69 décisions). Un tiers des sanctions visent des manquements à l’obligation de sécurité.

Risques opérationnels.

La CNIL a reçu 5 629 notifications de violations de données en 2024, soit +20 % vs 2023. Les incidents de très grande ampleur se multiplient, ce qui dégrade la disponibilité des services, la confiance utilisateur et la charge support.

La France est souvent dans les pays les plus mentionnés dans les classements de fuites de données comme celui de cybernews. Boulanger, Free, France Travail tout le monde y passe. Visiblement on a encore du taff pour améliorer le RGPD pour les développeurs.

Partie 4 – Outils et ressources RGPD pour les développeurs.

Pour la gestion des cookies, utilise une “Consent Management Platform” européenne : Axeptio, Didomi, ou un module maison qui bloque les scripts tant que le consentement n’est pas donné.
Préfère un outil d’analytics hébergé en Europe, comme Matomo ou Plausible.
Pour générer des jeux de test, Faker ou Mockaroo permettent de travailler sans données réelles.
Et pour gérer les secrets, Vault ou Infisical empêchent les clés de traîner dans Git.

Sur le site de la CNIL, lis le Guide RGPD pour les développeurs et la fiche sur les durées de conservation : c’est concret, avec des exemples par type de donnée.

Sur GDPR.eu, consulte la page “Core principles of the GDPR”, qui résume en clair les bases légales et les droits des utilisateurs, sans jargon juridique.

Conclusion – Une bonne hygiène plus que du juridique.

Le RGPD, c’est une loi européenne qui nous donne un cadre clair pour un logiciel qui construit la confiance avec ses utilisateurs.

Chaque champ, chaque log, chaque script participe à une relation entre ton code et ton utilisateur.
Respecter la vie privée, c’est maintenir cette confiance, jour après jour, comme une hygiène de développement.

Un code propre, c’est un code qui protège autant qu’il performe.
Et un jour, quelqu’un comme Marcel te demandera de supprimer ses données.
Ce jour-là, ton architecture dira si tu fais partie des équipes qui bricolent… ou de celles qui avaient prévu le coup.

Damien Cavaillès

Recent Posts

On accueille le nouveau CTO 🎉

Un nouveau capitaine technique débarque à la barre de WeLoveDevs ! Après le rachat par…

6 jours ago

AI Act for Developers : comprendre les 5 niveaux de risques

L’AI Act pour les développeurs, c’est la première loi vraiment impactante depuis le RGPD. Et…

2 semaines ago

Angular, mais en mode « easy » : interview avec Gaetan Redin.

"Venez, faites le module 1 et on en reparle." C’est le défi lancé par Gaetan…

3 semaines ago

OWASP Top 10 : 10 erreurs que les développeurs web font tous les jours (et comment les éviter)

L’OWASP Top 10, c’est un outil pour les développeurs web. Et pourtant, il est largement…

4 semaines ago

Monolithe vs Microservices : comment choisir la bonne architecture pour votre application ?

En 2025, le débat monolithe vs microservices n’est toujours pas tranché. Faut-il garder une architecture…

1 mois ago

Déminer l’objection « tu sais pas coder sans IA » en entretien.

"Tu sais pas coder sans IA." C’est devenu la nouvelle phrase passive-agressive des entretiens tech.…

2 mois ago