Sécuriser la confidentialité du presse-papiers sur Wayland et Hyprland avec un script wl-paste personnalisé

TL;DR : Les gestionnaires de presse-papiers Wayland/Hyprland peuvent divulguer des secrets.

Solution : Réduire la taille de l’historique.
Effacer l’historique au redémarrage.
Utiliser un script de surveillance sécurisé pour bloquer les données sensibles.
Désactiver complètement l’historique du presse-papiers pour une sécurité maximale.

Sécuriser les données du presse-papiers sous Wayland

J’utilise Wayland depuis un moment maintenant, plus précisément avec Hyprland, et globalement je suis vraiment satisfait du passage depuis X11. Le rendu est plus fluide, le modèle de sécurité est bien plus robuste, et les compositeurs rattrapent rapidement leur retard en termes de fonctionnalités.

Mais au passage, je suis tombé sur un problème subtil : la confidentialité du presse-papiers.

Le problème ne vient pas de Wayland lui‑même. En fait, Wayland est conçu pour être plus sécurisé que X11, les applications n’ont pas le même accès libre à vos contenus du presse‑papiers. Le problème vient de la façon dont la plupart des utilisateurs (moi y compris, au début) intègrent des gestionnaires de presse‑papiers comme cliphist, clipman, copyq ou clipse dans leur flux de travail.

Si vous suivez la wiki officielle de Hyprland sur les gestionnaires de presse-papiers, vous verrez souvent quelque chose comme ceci dans votre configuration :

# cliphist
exec-once = wl-paste --watch cliphist store

# clipman
exec-once = wl-paste -t text --watch clipman store --no-persist

# clipvault
exec-once = wl-paste --watch clipvault store

# clipse
exec-once = clipse -listen

# copyq
exec-once = copyq --start-server

# wl-clip-persist
exec-once = wl-clip-persist --clipboard regular

C’est pratique. Chaque morceau de texte que vous copiez est automatiquement ajouté à l’historique du presse‑papiers, et vous pouvez ensuite le rechercher ou le parcourir avec des outils comme rofi, fuzzel ou tofi.

Le problème ? Parfois, ce que vous copiez est hautement sensible : mots de passe, clés privées SSH, jetons d’API, seeds de portefeuilles crypto, données liées au travail. Tout cela va droit dans l’historique du presse‑papiers, stocké en clair dans une base SQLite locale. N’importe qui (ou n’importe quoi) ayant accès à votre compte peut le lire. Et si vous affichez votre historique dans une interface graphique ou le listez dans le terminal, vous êtes même vulnérable au simple coup d’œil par‑dessus l’épaule.

C’est ce qui m’a motivé à écrire cet article. Je vais vous expliquer :

  • Pourquoi les intégrations par défaut du presse‑papiers sont risquées.
  • Comment des gestionnaires comme cliphist stockent vos données.
  • Des conseils simples de durcissement (limiter la longueur de l’historique, effacer automatiquement au redémarrage).
  • Et surtout, comment j’ai construit un script wl‑paste personnalisé qui filtre les contenus sensibles avant qu’ils n’atteignent l’historique du presse‑papiers.

Comprendre le risque de l’historique du presse‑papiers

La gestion du presse‑papiers a toujours été un compromis entre commodité et sécurité. Pour voir pourquoi cela compte autant sous Wayland, comparons :

X11 vs. Wayland

  • X11 : Toute application en cours d’exécution peut consulter votre presse‑papiers à tout moment, sans aucune restriction. C’était une énorme faille de sécurité, mais tout le monde s’y est habitué.
  • Wayland : Les applications sont isolées, elles ne peuvent pas simplement récupérer votre presse‑papiers sans avoir le focus. C’est objectivement plus sûr.

Jusqu’ici, tout va bien. Mais il y a un piège :

Le problème des gestionnaires de presse‑papiers

Pour retrouver de la commodité (historique, recherche floue, sélecteurs graphiques), la plupart des utilisateurs Wayland installent un gestionnaire de presse‑papiers tel que : cliphist, clipman, copyq, clipse, clipvault

Puis ils le branchent à wl-paste comme ceci :

exec-once = wl-paste --watch cliphist store

À partir de ce moment, tout ce que vous copiez est automatiquement stocké : y compris les secrets.

Vecteurs d’attaque réels

1. Dump d’historique du presse‑papiers

N’importe qui ayant accès à votre compte utilisateur peut exécuter :

cliphist list | grep "BEGIN OPENSSH"

…et extraire immédiatement vos clés privées, jetons d’API, ou même des seeds de portefeuille crypto en 12/24 mots.

2. Observation par‑dessus l’épaule

Si vous parcourez l’historique avec une interface graphique comme rofi, wofi, fuzzel ou tofi, vous exposez effectivement toutes vos données sensibles en clair. Un simple coup d’œil, une capture d’écran ou un partage d’écran, et c’est compromis.

3. Stockage non chiffré

L’historique du presse‑papiers n’est pas seulement éphémère. Par exemple, cliphist stocke tout par défaut dans une base SQLite non chiffrée à : ~/.cache/cliphist/db ou ~/.cache/cliphist.db

Quiconque ayant accès au système de fichiers peut ouvrir ce fichier et faire défiler des centaines d’entrées passées.

La sortie de cliphist --help est explicite :

usage:
  $ cliphist <store|list|decode|delete|delete-query|wipe|version>
options:
  -config-path (default ~/.config/cliphist/config)
    overwrite config path to use instead of cli flags
  -db-path (default ~/.cache/cliphist/db)
    path to db
  -max-dedupe-search (default 100)
    maximum number of last items to look through when finding duplicates
  -max-items (default 750)
    maximum number of items to store
  -preview-width (default 100)
    maximum number of characters to preview

Cela signifie que vous pouvez trimballer 750 anciennes entrées de presse‑papiers : totalement non protégées.

Trouver l’équilibre entre productivité et sécurité

On comprend facilement pourquoi les gestionnaires de presse‑papiers sont si populaires. Pouvoir récupérer quelque chose que vous avez copié il y a 20 minutes, voire la veille, est incroyablement pratique. Développeurs, admin systèmes, auteurs… nous profitons tous d’un historique de presse‑papiers consultable.

Mais en réalité, vous avez rarement besoin de 750 entrées passées. La plupart du temps, votre flux de travail ne dépend que des quelques derniers éléments. Et en conserver davantage ne fait qu’augmenter votre surface d’attaque.

Voici quelques mitigations pratiques qui font déjà une grande différence :

1. Réduire la taille de l’historique du presse‑papiers

Par défaut, cliphist conserve 750 éléments. C’est beaucoup trop pour la plupart des utilisateurs. Le réduire à 20–50 éléments limite drastiquement l’exposition :

# ~/.config/cliphist/config
max-items = 50

C’est généralement suffisant pour garder ce qui est utile sans accumuler chaque chaîne copiée pendant des semaines.

2. Effacer l’historique du presse‑papiers au redémarrage

Autre pratique simple mais puissante : repartir de zéro à chaque redémarrage.

Vous pouvez effacer automatiquement l’historique en ajoutant cette ligne à la configuration de votre compositeur :

exec-once = cliphist wipe

Ou, pour les utilisateurs de systemd, vous pouvez créer un service utilisateur qui exécute cliphist wipe au démarrage. Cela garantit que toute donnée sensible stockée par accident est purgée à chaque nouvelle session.

3. Filtrage sélectif (la méthode intelligente)

Bien sûr, la meilleure solution est de ne jamais stocker de données sensibles. C’est là qu’intervient mon script personnalisé.

Au lieu de tout stocker aveuglément avec :

exec-once = wl-paste --watch cliphist store

…je fais passer le presse‑papiers par un script de filtrage sécurisé. Il détecte automatiquement quand le contenu copié ressemble à un mot de passe, une clé SSH, un jeton d’API ou une seed crypto : et refuse simplement de l’ajouter à l’historique.

exec-once = wl-paste --watch ~/.config/bin/cliphist-secure-store.sh

De cette manière, vous gardez tous les avantages de productivité de l’historique du presse‑papiers tout en réduisant drastiquement votre exposition.

4. Désactiver complètement l’historique du presse‑papiers (mode God)

Si vous n’avez pas besoin d’historique, vous pouvez le désactiver complètement. Il suffit de supprimer la ligne exec-once de la configuration de votre compositeur.

Cette méthode sera sécurisée à 100 %, mais vous ne pourrez plus rechercher ni parcourir votre historique. Rien n’est plus sûr.

Le script de presse‑papiers sécurisé

Voici le script que j’utilise dans ma propre configuration Hyprland. Il remplace la ligne en une seule commande et agit comme un filtre entre wl-paste et cliphist. Au lieu de tout stocker aveuglément, il analyse le contenu copié et décide s’il doit être enregistré ou ignoré.

#!/usr/bin/env bash
#
# Secure clipboard watcher for Hyprland + cliphist
#

set -euo pipefail

# ---- Configuration ---------------------------------------------------------

DEBUG=0   # set to 1 for debug output, 0 for silent

PM_APPS_REGEX='(Bitwarden|bitwarden|KeePassXC|keepassxc|1Password|1password|LastPass|lastpass|Enpass|enpass|Dashlane|dashlane|NordPass|nordpass|gnome-keyring|kwallet)'
SEED_COUNTS_REGEX='^(12|24)$'
KEY_MARKERS_REGEX='(BEGIN (OPENSSH|RSA|DSA|EC|ENCRYPTED)? ?PRIVATE KEY|ssh-|ecdsa-sha2-nistp)'
JWT_REGEX='(^|[^A-Za-z0-9_-])eyJ[A-Za-z0-9_-]{10,}.[A-Za-z0-9_-]+.'
GIT_TOKEN_REGEX='(gh[pous]_[A-Za-z0-9]{20,}|pat_[A-Za-z0-9]{20,})'
GOOGLE_TOKEN_REGEX='(^|[^A-Za-z0-9_-])ya29.[A-Za-z0-9_-]+'
HEX64_REGEX='^[A-Fa-f0-9]{64,}$'
B64_REGEX='^[A-Za-z0-9+/=]{40,}$'
ENTROPIC_REGEX='[A-Za-z0-9!@#$%^&*()_+=-]{16,}'

log_debug() {
    (( DEBUG == 1 )) && echo "[DEBUG] $*" >&2
}

# ---- Helpers ---------------------------------------------------------------

focused_app_is_pm() {
    local cls
    cls="$(hyprctl activewindow -j 2>/dev/null | jq -r '.class // ""')"
    log_debug "Focused app: '$cls'"
    [[ "$cls" =~ $PM_APPS_REGEX ]]
}

text_is_sensitive() {
    local data="$1"

    local wc_words
    wc_words="$(wc -w <<< "$data" | tr -d '[:space:]')"

    if [[ "$wc_words" =~ $SEED_COUNTS_REGEX ]]; then
        log_debug "Blocked: seed phrase ($wc_words words)"
        return 0
    fi

    if grep -qiE "$KEY_MARKERS_REGEX" <<< "$data"; then
        log_debug "Blocked: private key marker"
        return 0
    fi

    if grep -qE "$JWT_REGEX" <<< "$data"; then
        log_debug "Blocked: JWT token"
        return 0
    fi

    if grep -qE "$GIT_TOKEN_REGEX" <<< "$data"; then
        log_debug "Blocked: GitHub token"
        return 0
    fi

    if grep -qE "$GOOGLE_TOKEN_REGEX" <<< "$data"; then
        log_debug "Blocked: Google token"
        return 0
    fi

    if grep -qE "$HEX64_REGEX" <<< "$data"; then
        log_debug "Blocked: long hex string"
        return 0
    fi

    if grep -qE "$B64_REGEX" <<< "$data"; then
        log_debug "Blocked: long base64 string"
        return 0
    fi

    if grep -qE "$ENTROPIC_REGEX" <<< "$data"; then
        log_debug "Blocked: entropy heuristic"
        return 0
    fi

    return 1
}

# ---- Main flow -------------------------------------------------------------

clip_content=$(cat)

if focused_app_is_pm; then
    log_debug "Skipped: password manager focused"
    exit 0
fi

if text_is_sensitive "$clip_content"; then
    exit 0
fi

log_debug "Stored in cliphist: '${clip_content:0:60}'..."
printf "%s" "$clip_content" | cliphist store

Comment ça fonctionne

1. Détection du gestionnaire de mots de passe

En utilisant hyprctl activewindow, le script vérifie si l’application ayant le focus est un gestionnaire de mots de passe (KeePassXC, Bitwarden, 1Password, etc.). Si oui, le stockage dans l’historique est complètement ignoré.

Vous pouvez ajouter vos propres applications à la liste si vous voulez leur permettre de stocker des données sensibles.

PM_APPS_REGEX='(Bitwarden|bitwarden|KeePassXC|keepassxc|1Password|1password|LastPass|lastpass|Enpass|enpass|Dashlane|dashlane|NordPass|nordpass|gnome-keyring|kwallet)'

2. Motifs de données sensibles

Le script analyse le contenu du presse‑papiers à la recherche de formats de secrets courants :

  • Seeds de portefeuilles crypto en 12/24 mots
  • Clés privées SSH (BEGIN OPENSSH PRIVATE KEY)
  • Jetons JWT (eyJ…)
  • Tokens d’accès personnels GitHub (ghp, pat)
  • Jetons OAuth Google (ya29.)
  • Longues chaînes base64 ou hexadécimales
  • Chaînes aléatoires à forte entropie (fréquent pour les secrets)

En cas de correspondance, le contenu est jeté.

3. Stockage des données sûres

Si le contenu passe les contrôles, il est transmis à cliphist store comme d’habitude.

4. Journalisation de debug

Mettez DEBUG=1 pour voir pourquoi certains éléments ont été bloqués. Exemple de sortie :

[DEBUG] Blocked: seed phrase (12 words)

Intégration avec Hyprland

La mise en place du watcher sécurisé pour le presse‑papiers est simple. Vous allez simplement remplacer la ligne par défaut wl-paste --watch cliphist store de la wiki Hyprland par votre script personnalisé.

1. Sauvegarder le script

Placez le script à un endroit persistant, par exemple :

~/.config/bin/cliphist-secure-store.sh

Rendez‑le exécutable :

chmod +x ~/.config/bin/cliphist-secure-store.sh

2. Mettre à jour la configuration Hyprland

Dans votre hyprland.conf, changez la ligne exec-once en :

exec-once = wl-paste --watch ~/.config/bin/cliphist-secure-store.sh

Cela garantit que tous les nouveaux événements de presse‑papiers sont filtrés par votre script avant d’atteindre cliphist.

3. Installer les dépendances

Le script repose sur quelques outils :

  • wl-clipboard : fournit wl-paste et wl-copy.
  • cliphist : votre gestionnaire d’historique de presse‑papiers.
  • jq : utilisé pour analyser la sortie JSON de Hyprland depuis hyprctl.

Sur les distributions basées sur Arch (CachyOS, Arch, Manjaro) :

sudo pacman -S wl-clipboard cliphist jq

Sur les systèmes basés sur Debian/Ubuntu :

sudo apt install wl-clipboard jq

Sur les systèmes Fedora/RedHat :

dnf install wl-clipboard jq

4. Optionnel : activer le mode debug

Si vous voulez vérifier que le filtrage fonctionne, réglez DEBUG=1 dans le script. Puis redémarrez Hyprland, copiez un secret (comme l’en‑tête d’une clé SSH), et consultez les logs :

journalctl --user -f | grep cliphist-secure-store

Vous devriez voir des messages du type :

[DEBUG] Blocked: private key marker

Démo & exemples

Mettons le watcher sécurisé du presse‑papiers à l’épreuve.

1. Texte normal

Copiez une chaîne inoffensive :

echo "hello world" | wl-copy

Consultez votre historique :

cliphist list | head -n 1

Résultat : ”hello world” apparaît en tête de liste comme prévu.

2. Clé privée SSH

Copiez maintenant quelque chose qui ressemble à une clé privée :

echo "-----BEGIN OPENSSH PRIVATE KEY-----" | wl-copy

Vérifiez à nouveau votre historique :

cliphist list | grep "OPENSSH"

Résultat : Aucune correspondance : le script l’a bloqué.

Si DEBUG=1 est activé, vous verrez :

[DEBUG] Blocked: private key marker

3. Seed de portefeuille crypto

Essayez une seed de 12 mots :

echo "apple banana cat dog eagle flower guitar hotel island jungle kite lemon" | wl-copy

Lancez :

cliphist list | grep "apple"

Résultat : Rien n’est stocké : les seeds sont automatiquement supprimées.

4. Fenêtre de gestionnaire de mots de passe

Ouvrez KeePassXC, donnez le focus à sa fenêtre, puis copiez n’importe quel texte à l’intérieur.

Même si ce n’est que “test123”, le script détectera la classe de la fenêtre active et ignorera le stockage.

Avec le mode debug, vous verrez :

[DEBUG] Skipped: password manager focused

5. Après un redémarrage (durcissement optionnel)

Si vous avez configuré cliphist wipe au démarrage, votre historique sera vide à chaque nouvelle session :

cliphist list
# no output

Cela garantit que rien de sensible ne survit aux redémarrages.

Limitations & pistes d’amélioration

Cette configuration améliore considérablement la sécurité de l’historique du presse‑papiers sous Wayland, mais ce n’est pas une solution miracle. Il reste quelques points à garder à l’esprit :

1. Les regex et heuristiques ne sont pas parfaites

  • Le script bloque de nombreux formats de secrets courants, mais il est toujours possible que quelque chose de sensible passe entre les mailles du filet s’il ne correspond à aucun motif.
  • À l’inverse, certains faux positifs peuvent survenir : une chaîne aléatoire peut ressembler à un jeton et être jetée.

2. Le stockage en clair demeure

  • Même avec filtrage, les entrées de presse‑papiers qui sont stockées le sont dans une base SQLite non chiffrée (ou un autre backend de stockage selon l’outil).
  • Toute personne ayant accès à votre répertoire personnel peut toujours l’ouvrir et parcourir l’historique.

3. Lacunes spécifiques aux applications

  • La détection de fenêtre repose sur les noms de classe (hyprctl activewindow -j). Si votre gestionnaire de mots de passe ou application crypto utilise un autre nom de classe, vous devrez étendre la regex.
  • C’est facile à ajuster, mais cela nécessite un peu de maintenance manuelle.

Améliorations futures

  • Règles configurables : déplacer les motifs regex dans un fichier de configuration séparé afin que les utilisateurs puissent personnaliser sans modifier le script.
  • Support du chiffrement : idéalement, les gestionnaires de presse‑papiers comme cliphist pourraient proposer un chiffrement optionnel des données stockées.
  • Intégration systemd : envelopper le script dans une unité systemd --user pour un logging plus simple, un redémarrage automatique et un activation/désactivation facile.
  • Effacement sélectif : ajouter un effacement automatique programmé (par ex. toutes les 24 heures), pas uniquement au redémarrage.

Conclusion

L’historique du presse‑papiers est l’une de ces fonctionnalités auxquelles on ne réfléchit pas vraiment… jusqu’au moment où l’on réalise à quel point des données sensibles peuvent s’y retrouver. Sous Wayland et Hyprland, le modèle de sécurité est plus robuste que sous X11, mais intégrer un gestionnaire de presse‑papiers sans précaution réintroduit de vieux risques : mots de passe, clés SSH, jetons d’API et seeds crypto se retrouvant tous en clair dans une base SQLite.

En combinant quatre pratiques simples, vous pouvez réduire drastiquement votre exposition :

  • Réduire la taille de l’historique : ne gardez pas 750 entrées quand 20–50 suffisent.
  • Effacer l’historique au redémarrage : commencez chaque session sur une base saine.
  • Filtrer les données sensibles avec un watcher personnalisé : ne laissez jamais les secrets entrer dans l’historique.
  • Désactiver totalement l’historique : si vous n’avez pas réellement besoin d’historique, l’option la plus sûre est de retirer l’intégration du gestionnaire de presse‑papiers de votre configuration. Rien ne sera jamais enregistré, donc rien ne pourra fuiter, sécurité maximale au prix de la commodité.

Avec cette configuration, vous conservez les bénéfices de productivité des gestionnaires de presse‑papiers tout en évitant les pièges les plus évidents. Ce n’est pas parfait, un chiffrement et un filtrage plus intelligent seraient encore mieux, mais c’est une énorme amélioration par rapport à la configuration par défaut.

Si vous utilisez Hyprland (ou n’importe quel compositeur Wayland) et que vous dépendez de l’historique du presse‑papiers, prenez quelques minutes pour renforcer votre configuration. Votre futur vous, ainsi que vos clés SSH, vos mots de passe et vos portefeuilles crypto, vous en seront reconnaissants.

30 septembre 2025 par Julien Turbide