💡 Exemple complet disponible sur GitHub :
sanitize-office-document-pii-python

Les données que personne ne révise avant d’envoyer

Un rapport trimestriel du conseil est envoyé à un auditeur externe. Le texte est impeccable ; trois cycles de révision l’ont assuré. Le fichier lui‑même raconte une autre histoire. Ses propriétés indiquent encore l’analyste qui l’a rédigé, le responsable qui l’a retravaillé, la filiale de l’entreprise qui possède le modèle, un horodatage LastPrinted de la nuit précédant la date limite, et un identifiant d’approbateur SharePoint provenant du workflow interne de validation. Aucun de ces éléments n’apparaît dans le corps du document. Tout cela voyage avec le fichier.

La suppression de PII est un flux de travail GroupDocs.Metadata pour Python via .NET qui élimine ces propriétés porteuses d’identité des fichiers Word, Excel et PowerPoint de façon programmatique. Cet article compare les trois approches offertes par l’API : suppression guidée par balises pour les champs d’identité, suppression par motif de nom pour les familles de propriétés comme les commentaires et les révisions, et l’appel unique sanitize() qui efface tout. Vous verrez également l’étape que la plupart des scripts de désinfection négligent, à savoir une analyse de vérification qui prouve que le nettoyage a réellement tenu.

Pourquoi les PII dans les métadonnées méritent leur propre pipeline

Les outils de révision de contenu vérifient ce que les gens lisent. Ils ne vérifient pas ce que les systèmes de fichiers stockent, et c’est cet écart qui génère les incidents de conformité. Une demande GDPR couvre les données personnelles dans les champs Author et Manager autant que les données présentes dans le texte. La découverte juridique lit les compteurs de révision et les totaux de temps d’édition pour reconstituer la durée de négociation d’un document de position. Les évaluateurs d’appels d’offres peuvent cartographier votre structure organisationnelle à partir des propriétés du workflow SharePoint, et les champs de commentaire d’un communiqué de presse conservent les noms des relecteurs aux côtés des remarques de phase de brouillon. Chacun de ces éléments constitue une découverte. Aucun d’eux n’est visible dans le corps du document.

Prérequis

Avant de commencer, assurez‑vous d’avoir :

  • Python 3 avec pip
  • GroupDocs.Metadata pour Python via .NET, fixé dans le dépôt d’exemple à la version 26.5
  • Un fichier Office contenant de vraies propriétés pour s’exercer

Installation

pip install groupdocs-metadata-net==26.5

Le dépôt compagnon fournit un DOCX d’exemple et exécute chaque extrait ci‑dessous comme un pipeline validé.

Méthode 1 : Suppression d’identité basée sur les balises

Les quatre champs les plus sensibles, Author, LastSavedBy, Manager et Company, portent des noms internes différents selon les formats Office. Le système de balises résout ce problème : au lieu de nommer les propriétés, le prédicat demande tout ce qui est balisé comme une personne ou une société.

# Match identity properties by meaning, not by format-specific name
with Metadata("board-report.docx") as metadata:
    removed = metadata.remove_properties(lambda p:
        Tags.person.creator in list(p.tags)     # Author, LastSavedBy
        or Tags.person.editor in list(p.tags)
        or Tags.person.manager in list(p.tags)
        or Tags.corporate.company in list(p.tags))
    metadata.save("board-report-clean.docx")

print(f"{removed} identity properties removed")

Points clés :

  • Indépendance du format : la même lambda nettoie DOCX, XLSX et PPTX parce que les balises classifient par rôle.
  • Résultat comptable : remove_properties renvoie le nombre de propriétés correspondantes, ce qui doit figurer dans votre journal d’audit.
  • Sémantique de copie : enregistrer dans un nouveau chemin conserve l’original pour vos archives.

💡 Astuce : ce passage préserve les champs Title, Subject et autres champs descriptifs, de sorte que le fichier reste convivial pour la recherche et l’indexation DMS.

Méthode 2 : Suppression par motif de nom pour les familles de propriétés

Les balises couvrent les concepts classifiés. Des familles entières de champs fuyants se situent en dehors de cette classification : propriétés de commentaire, compteurs de révision, tampons du workflow SharePoint. Pour celles‑ci, faites correspondre le nom de la propriété elle‑même.

# Comment fields often live in custom properties the tag system
# does not classify, so match them by name substring
with Metadata("board-report.docx") as metadata:
    removed = metadata.remove_properties(lambda p:
        p.name is not None and (
            "Comment" in p.name
            or "Reviewer" in p.name
            or "Reviewed" in p.name))
    metadata.save("board-report-no-comments.docx")

La même structure gère les deux autres familles ; seule la liste des sous‑chaînes change :

Famille Sous‑chaînes à correspondre
Piste de révision Revision, TrackedChange, LastPrinted, TotalEditingTime, EditTime
Serveur / workflow Server, Workflow, Approver, ContentType, Template

Cela échange précision contre portée : "Comment" capture également Comments et CommentCount, ce qui est généralement ce qu’une passe de désinfection recherche. Des sous‑chaînes larges peuvent aussi correspondre à des champs de modèle inoffensifs, donc comparez le nombre retourné aux attentes.

💡 Astuce : exécutez chaque famille comme une passe distincte lorsque votre journal d’audit nécessite des comptes par catégorie ; regroupez les sous‑chaînes dans un seul prédicat lorsqu’il n’en est pas besoin.

Méthode 3 : L’appel unique sanitize()

Lorsque le fichier quitte l’organisation et qu’aucune couche de métadonnées ne doit survivre, cessez d’écrire des prédicats.

# One call, every detected metadata package
with Metadata("board-report.docx") as metadata:
    removed = metadata.sanitize()
    metadata.save("board-report-final.docx")

print(f"sanitize() removed {removed} properties")

sanitize() efface chaque paquet détecté par la bibliothèque : champs d’identité du document‑info, commentaires, historique des révisions, auteurs des modifications suivies, et parties OOXML personnalisées. Le comportement est documenté sur la page Clean metadata. Sa force est aussi son coût. Title et Subject disparaissent avec les PII, ce qui explique pourquoi il convient à la porte d’exportation plutôt qu’au milieu d’un workflow collaboratif.

Ai‑je besoin des quatre passes ciblées ?

Non. Chaque passe existe parce qu’une équipe différente possède le risque. Les champs d’identité dérangent les responsables de la vie privée, les traces de commentaires dérangent le service juridique, les compteurs de révision dérangent les négociateurs, et les champs serveur dérangent la sécurité. Exécutez les passes qui correspondent à vos réviseurs, dans n’importe quel ordre, chaque passe écrivant sa propre copie de sortie. Quand personne n’a besoin de champs survivants, passez directement à sanitize() et vérifiez.

Comparaison des trois approches

Méthode Idéal pour Avantages clés Limitations
Suppression guidée par balises Copies de travail, pipelines multi‑format Indépendance du format, préserve les champs descriptifs Ne couvre que les concepts classés par balises
Suppression par motif de nom Commentaires, révisions, champs serveur Atteint les propriétés personnalisées que les balises manquent Les sous‑chaînes nécessitent un ajustement selon l’environnement
sanitize() complet Export final hors de l’organisation Ne peut pas manquer une propriété oubliée Efface aussi les champs inoffensifs

Les approches se combinent naturellement : passes ciblées pendant que le document est actif, sanitize() lorsqu’il est expédié.

Vérifiez avant de faire confiance

Un appel de suppression qui renvoie un compte n’est pas la preuve que le fichier est propre. Le dépôt termine chaque exécution en rouvrant la sortie désinfectée et en la scannant avec find_properties, en utilisant un prédicat qui combine les règles de balises et les règles de nom de toutes les passes ci‑dessus.

def is_pii(p):
    if p.name is None:
        return False
    return (
        Tags.person.creator in list(p.tags)
        or Tags.person.editor in list(p.tags)
        or Tags.person.manager in list(p.tags)
        or Tags.corporate.company in list(p.tags)
        or any(n in p.name for n in (
            "Comment", "Reviewer", "Revision", "TrackedChange",
            "Classification", "Department", "Server", "Workflow")))

with Metadata("board-report-final.docx") as metadata:
    for p in metadata.find_properties(is_pii):
        value = (str(p.interpreted_value) if p.interpreted_value is not None
                 else (str(p.value) if p.value is not None else ""))
        if value and value not in ("0", "0.0"):
            print(f"LEAK {p.name}={value}")

La version complète du dépôt classe les survivants en deux catégories, et la distinction importe. Les fuites de métadonnées doivent être nulles. Les résidus au niveau du contenu, les bulles de commentaires Word et les modifications suivies vivant dans word/document.xml, sont du contenu du corps que l’API de métadonnées ne peut pas atteindre ; les supprimer nécessite une bibliothèque d’édition de contenu telle qu’Aspose.Words. Un rapport honnête nomme les deux catégories au lieu de déclarer la victoire dès la première. La première fois que j’ai exécuté ce scan sur un fichier « clean », il a signalé un champ Department qu’un modèle d’entreprise réintégrerait discrètement depuis des mois.

Bonnes pratiques et astuces

  • Désinfectez des copies, jamais les originaux : chaque extrait écrit dans un nouveau chemin, conservant la source pour vos archives et vos règles de rétention.
  • Consignez les comptes : les valeurs de retour de remove_properties et sanitize() constituent votre piste d’audit. Stockez‑les par fichier, par passe.
  • Intégrez la vérification dans le CI : un contrôle de fuite qui fait échouer la build capture les régressions de modèle le jour même où elles surviennent, pas le jour où un client les remarque.
  • Respectez la frontière métadonnées/contenu : ne déclarez jamais un fichier propre tant que des commentaires au niveau du corps subsistent ; signalez‑les comme une découverte séparée.
  • Licence : le mode d’évaluation reproduit tout ce qui est présenté dans cet article ; utilisez une licence en production afin qu’aucune marque d’évaluation n’apparaisse sur les fichiers sortants.

Conclusion

Trois approches, une règle de décision. Faites correspondre par balise lorsque le concept est classifié et que le fichier doit rester exploitable. Faites correspondre par nom lorsque la famille vit dans des propriétés personnalisées. Appelez sanitize() lorsque le fichier franchit la frontière de confiance, et vérifiez avec une analyse de relecture, quelle que soit la voie choisie.

Prêt à aller plus loin ? Voici quelques étapes suivantes :

Ressources supplémentaires

Des questions ou envie de partager votre implémentation ? Contactez‑nous sur le support forum.