Le client a chiffré puis envoyé l’espace de travail : pourquoi vous n’ouvrez pas ce texte chiffré local

Le 18 septembre 2026, le développeur ferstar faisait de la place sur le disque et a constaté qu’un client de programmation assistée, une fois la session ouverte, empaquetait tout l’espace de travail dans une archive chiffrée, puis tentait de l’envoyer directement vers un stockage objet. L’archive était du texte chiffré. La clé publique RSA qui enveloppait la clé de contenu était émise par le serveur sur le moment, et la clé privée correspondante n’atterrissait jamais sur la machine. Quelques centaines de mégaoctets de fichiers « déjà chiffrés » restaient sur le disque, que ni vous ni le client ne pouviez ouvrir. Le 21 septembre, l’éditeur a annoncé l’ouverture du code et le retrait du chemin d’envoi. Ces mots — « envoi chiffré » — ne sont pas devenus du zéro connaissance pour autant.

Commencez par la conclusion : « déjà chiffré » dit seulement que les octets empaquetés ne sont pas un espace de travail en clair. Cela ne dit pas que vous détenez la clé de déchiffrement, et cela ne dit pas que le cloud ne peut pas lire le contenu. Dans un chiffrement par enveloppe, une clé symétrique est enveloppée avec une clé publique que le serveur vient d’émettre, et la clé privée reste dans le cloud. Le but du dessin est que le cloud puisse ouvrir. Ce que vous pouvez contrôler sur cette machine tient en trois points : pouvez-vous ouvrir ce texte chiffré vous-même, Network montre-t-il le clair de l’espace de travail, et un nouvel archive en attente apparaît-il encore après avoir coupé les interrupteurs. Ne lisez pas « AES a tourné en local » comme « seul moi peux déchiffrer ».

Répondre à l’intention de recherche en une phrase

Le chiffrement du trajet et « vous détenez la clé » ne sont pas la même couche. Un client peut faire tourner AES sur cette machine, transformer un espace de travail en texte chiffré, et envoyer ce texte chiffré vers un stockage objet. Si la clé publique qui enveloppe la clé de contenu vient du serveur, et si la clé privée n’est jamais entrée dans cet ordinateur, le fichier n’est pas une sauvegarde que vous restaurez. C’est une enveloppe que seul le cloud peut ouvrir. Un observateur du trajet ne voit pas le clair. Le serveur qui tient la clé privée, lui, le voit.

Cette note s’adresse à qui vient de lire un titre sur un client qui chiffre un espace de travail avant l’envoi, et qui veut séparer « le texte chiffré est sur le disque » du zéro connaissance. Elle s’adresse aussi aux développeurs qui doivent remettre un dépôt ou une clé à un collègue sans remettre le droit de déchiffrer à un éditeur. Elle ne remplace pas l’avis de l’éditeur, et ce n’est pas un guide de désinstallation pour un éditeur précis. Ce qu’il faut emporter : qui tient la clé dans un chiffrement par enveloppe, quelle étendue le manifeste en clair a déjà écrite, ce que « détruire tout de suite » ne prouve pas, et comment contrôler sur cette machine si vous pouvez ouvrir le fichier.

Ce que le démontage a fixé

Le 18 septembre 2026, ferstar a publié l’enquête. Ce n’était pas un concours de capture de paquets. C’était un nettoyage de disque. Le dossier local ~/.zcode dépassait 700 Mo. Sous v2/checkpoints/ se trouvait un .enc d’environ 313 Mo. Le fichier d’état à côté indiquait un espace de travail d’environ 345 Mo, un kind à baseline, et un failureCount à 564. Le dépôt lui-même faisait environ 10 Go. Une fois les dépendances écartées, les 345 Mo restants étaient presque tous des fichiers de cœur de projet.

Il a reconstitué l’envoi en deux étapes. D’abord, le client appelait POST /api/v1/snapshot/upload-credential sur zcode.z.ai. Le serveur renvoyait un identifiant d’instantané, une signature de formulaire pour le stockage objet, un plafond de taille, et une clé publique RSA pour ce tour. Ensuite, la machine construisait un tar.gz, le chiffrait avec une clé symétrique à usage unique en AES-256-CTR, enveloppait cette clé avec RSA-OAEP-SHA256, et postait tar.gz.enc en formulaire directement vers Alibaba Cloud OSS. Un rappel du stockage enregistrait l’objet auprès du backend de l’éditeur. Le serveur d’application ne touchait pas le fichier chiffré. L’enregistrement et la clé privée restaient dans le cloud.

Le périmètre n’était pas l’arbre de travail courant. Un manifeste local en clair listait 42 411 fichiers : .git/lfs/ environ 196,1 Mo (56,8 %), .git/objects/ environ 102,2 Mo (29,6 %), .git/logs/ environ 0,6 Mo, et le source plus la documentation environ 46,2 Mo (13,4 %). .git représentait 86,6 % du paquet. Un envoi réussi aurait donné au cloud l’historique des commits, des secrets déjà retirés de l’arbre mais encore présents dans le magasin d’objets, les noms de branches jamais poussées, et les hôtes d’intranet dans .git/config. Un second manifeste, transversal aux espaces de travail, hachait la configuration globale et l’emportait aussi.

À 17 h 44 le 18 septembre, l’éditeur a posté dans sa communauté d’utilisateurs. Il disait que l’envoi venait d’un index de dépôt de code activé par défaut, utilisé pour les points de contrôle de session, le retour de version et le Repo Wiki, et que les données étaient détruites dès que le Wiki était généré. Le 21 septembre, le National Business Daily a rapporté que ZCode ouvrirait le code du client ; l’Académie chinoise des technologies de l’information et des communications indiquait que le seau zcode-prod ne contenait aucune donnée ; NSFOCUS indiquait que le seau et les objets avaient été supprimés ; et le client v3.14.0 avait retiré la génération d’instantanés et le chemin d’envoi. ferstar a ajouté un résultat scindé : le projet commercial de 313 Mo dépassait le plafond, a été retenté 564 fois, et n’a jamais quitté le réseau local. Un autre espace de travail, un dépôt public de 538 fichiers, compressé et chiffré à environ 15 Ko, avait le statut « accepté par le serveur ». Donc « quelque chose a-t-il quitté cette machine ? » — au moins ce petit-là, oui.

Pourquoi le chiffrement par enveloppe n’est pas un fichier que vous ouvrez

AES-256-CTR plus RSA-OAEP, c’est l’enveloppe du manuel. Le contenu est chiffré avec une clé symétrique de courte durée. Cette clé est ensuite enveloppée avec une clé publique. Les noms d’algorithmes ont l’air solides. Qui peut lire le fichier dépend de l’origine de la clé publique et de l’endroit où siège la clé privée. Le compte rendu est explicite : la clé publique était émise quand le client demandait un justificatif d’envoi, la clé privée correspondante n’entrait jamais dans cet ordinateur, et ouvrir l’enveloppe avec des clés privées déjà présentes sur la machine a échoué. Le client lui-même ne pouvait pas ouvrir le texte chiffré sur le disque.

C’est l’inverse d’une sauvegarde que vous restaurez. Time Machine, les objets Git locaux, et un fichier que vous chiffrez avec une phrase secrète puis que vous copiez ailleurs gardent le matériau de déchiffrement de votre côté : une phrase secrète, une clé locale, ou un trousseau que vous ouvrez. Quand le serveur seul tient la clé privée, le but change. Un tiers sur le trajet ne doit pas voir les octets. Après l’arrivée, le cloud doit pouvoir les ouvrir. La phrase de ferstar fixe l’usage : une clé que seul le serveur peut utiliser sert au serveur qui lit votre code. Elle ne sert pas à un retour arrière pour vous.

He Yuan, du centre de recherche en droit des données de l’université Jiao Tong de Shanghai, a dit au National Business Daily une chose plus étroite. Le chiffrement est une mesure de sécurité. Ce n’est pas une anonymisation, et il ne remplace ni l’information ni la minimisation. Quand le prestataire détient encore la capacité de déchiffrer, les données chiffrées peuvent encore être retrouvées et traitées. « Supprimer tout de suite après usage » ne fait que réduire la conservation longue. Cela ne répond pas à la question de savoir si la première collecte était nécessaire. Mettez les deux phrases ensemble : la force de l’algorithme ne prouve pas qui tient la clé, et une déclaration de destruction ne prouve pas le périmètre de collecte.

N’utilisez pas un dépôt de production, une clé cloud encore active, ni du code client pour « reproduire l’envoi ». Contrôlez si un texte chiffré en attente est déjà sur cette machine, quel chemin et quel nombre d’échecs le fichier d’état enregistre, et si vous pouvez ouvrir le fichier vous-même. Renvoyer le dépôt vivant ne remet pas la clé privée dans vos mains.

Le manifeste en clair a déjà écrit le périmètre

Vous n’ouvrez pas le texte chiffré. Cela ne veut pas dire que le périmètre est une supposition. La liste de fichiers écrite au moment de l’empaquetage est restée sur le disque, et elle était en clair. Ces 42 411 lignes séparent « l’arbre source courant » de « la vie du dépôt ». L’arbre courant représentait environ 13,4 %. Le reste était le cache LFS, le magasin d’objets complet, et le reflog. Une clé d’API déjà retirée de l’arbre de travail peut encore siéger dans .git/objects si elle a un jour été commitée. Un nom de branche non poussée peut exposer une fonction qui n’est pas encore publique. Un nom d’hôte Git d’intranet vit dans .git/config. Vous n’avez pas besoin d’ouvrir le texte chiffré pour voir, du côté du manifeste, qu’il a été empaqueté.

Deux interrupteurs à l’écran ont l’air d’interrupteurs généraux. Dans le code, ils ne l’étaient pas. Une fois le compte rendu aligné, « améliorer l’expérience » ne réglait que la possibilité d’utiliser les données pour l’entraînement du modèle, et « index d’instantané du dépôt » ne réglait que le fait que le cloud construise un index. L’empaquetage et l’envoi direct continuaient tant que le JWT de session était valide. Les points de capture se plaçaient avant chaque invite, et sur repo-wiki-update à la fin d’une tâche. Une session active a été journalisée jusqu’à 62 captures. Environ une demi-heure après la suppression manuelle de l’archive en attente, un nouveau fichier de 313 Mo est apparu, et le compteur d’échecs est passé de 564 à 565. Supprimer le fichier, ce n’est pas couper l’interrupteur.

La politique de confidentialité archivée le 18 septembre indiquait encore une dernière mise à jour au 2026-06-15. Le périmètre de collecte qu’elle décrivait était le texte, les fichiers et le code soumis dans une conversation. Elle ne disait pas « après l’ouverture de session, empaqueter automatiquement l’espace de travail complet et l’historique Git ». La politique peut soutenir une affirmation : l’éditeur a déclaré collecter ce que vous soumettiez dans une session. Elle ne peut pas en soutenir une autre : qu’un instantané complet était déjà écrit sur la page que vous aviez acceptée. Les interrupteurs et la politique doivent être confrontés à l’artefact. Y a-t-il un nouveau .enc en local ? Le workspacePath du fichier d’état pointe-t-il vers le projet commercial que vous écrivez ?

Ce que « chiffré » et « détruit tout de suite » prouvent chacun

Découpez les phrases de l’actualité en « ceci soutient » et « ceci ne soutient pas ». C’est plus stable que de suivre les adjectifs. Un texte chiffré sur le disque ne soutient que ceci : les octets empaquetés ne sont pas un arbre de répertoires en clair. La destruction immédiate ne soutient que ceci : l’éditeur dit ne pas garder cet objet longtemps après la génération du Wiki. Une recherche dans l’arbre ouvert qui ne trouve pas /api/v1/snapshot/upload-credential ne soutient que ceci : le chemin a disparu de l’arbre public maintenant. Un seau évalué comme ne contenant aucune donnée ne soutient que ceci : ce seau était vide au moment de l’évaluation.

Aucune de ces phrases ne couvre l’autre face. Le texte chiffré ne soutient pas « vous pouvez restaurer l’espace de travail ». La destruction immédiate ne soutient pas « personne ne tenait la clé privée avant la suppression », et elle ne soutient pas « le périmètre de collecte correspondait à l’option que vous aviez cochée ». Un arbre ouvert aplati en deux commits ne sert pas à comparer comment l’ancien sidecar était écrit. Un seau vidé après coup ne se rembobine pas pour montrer qui a déchiffré ou copié des objets déjà acceptés avant le 18 septembre. ferstar a noté la tension : si le retour de point de contrôle exigeait vraiment un envoi complet vers le cloud, cela se heurte à « détruire tout de suite après génération » sur la chronologie. L’implémentation des points de contrôle dans l’arbre ouvert est un diff Git local. Les métadonnées sont du JSON sous ~/.zcode/checkpoints/. Elles ne dépendent pas de ce chemin d’envoi.

Ce que vous voyez Ce que cela peut soutenir Ce que cela ne peut pas soutenir
Un .enc sur le disque, étiqueté AES-256 Les octets empaquetés ne sont pas un espace de travail en clair Seul vous pouvez déchiffrer, et le cloud ne lit pas le contenu
La clé publique RSA est émise quand le client demande un justificatif La clé privée qui ouvre l’enveloppe n’est pas sur cet ordinateur C’est une sauvegarde pour restaurer sur un autre appareil
Vous avez coupé « améliorer l’expérience » et « index du dépôt » Le consentement d’entraînement ou l’index cloud a peut-être cessé L’empaquetage et l’envoi direct se sont arrêtés avec eux
L’éditeur dit que les données sont détruites juste après le Wiki L’éditeur dit ne pas garder cet objet sur la durée Le premier paquet correspondait à l’interrupteur cliqué
Une évaluation dit que le seau ne contient aucune donnée Ce seau était vide au moment de l’évaluation Les objets acceptés plus tôt n’ont jamais été déchiffrés ni copiés
Le fichier de 313 Mo a échoué 564 fois Cet instantané de projet commercial n’a pas été envoyé Aucun espace de travail n’a jamais quitté la machine d’un utilisateur

Ce que vous pouvez contrôler sur cet appareil

Un slogan n’est pas une preuve. Les contrôles ci-dessous ne couvrent que trois couches que vous tenez : un artefact en attente est-il déjà sur cette machine, une requête a-t-elle emporté le clair de l’espace de travail, et pouvez-vous ouvrir ce texte chiffré vous-même. Ne poussez pas un autre « envoi de test » dans un dépôt de production.

  1. Regardez le répertoire de données local avant la page marketing. Dans le dossier de points de contrôle ou de cache d’un client de programmation assistée, un .enc de plusieurs centaines de mégaoctets à côté d’un fichier d’état qui enregistre workspacePath, encryptedSizeBytes et failureCount signifie que l’empaquetage a déjà eu lieu. Un chemin qui correspond au projet que vous écrivez est une preuve plus dure que « nous n’envoyons que le contexte de conversation ».
  2. Ouvrez les outils de développement ou un observateur réseau du système et cochez Preserve log. Lisez seulement les lignes de requête et les noms d’hôte : y a-t-il un appel qui demande un justificatif d’envoi, et y a-t-il un POST de formulaire droit vers le stockage objet ? Vous contrôlez si le texte chiffré a quitté cette machine, vous ne renvoyez pas le dépôt. Si le corps contient du source, une phrase secrète, ou un .pem en clair, cette couche a déjà échoué.
  3. Posez une question que vous pouvez finir : puis-je ouvrir ce texte chiffré local avec ma propre phrase secrète ou une clé privée sur cette machine ? Si vous ne le pouvez pas, et si l’éditeur dit aussi que le client ne le peut pas, la clé n’est pas de votre côté. Ce n’est que si vous pouvez l’ouvrir qu’il est juste d’appeler le fichier une sauvegarde pour vous.
  4. Coupez chaque interrupteur dont le nom évoque la confidentialité, l’index ou l’amélioration. Attendez un cycle de session. Regardez ensuite : y a-t-il une nouvelle archive en attente dans le dossier de points de contrôle, et le compteur d’échecs a-t-il continué de monter ? L’étiquette d’un interrupteur ne prouve pas une coupure générale. Un nouveau fichier, oui.
  5. Quand il vous faut un fichier que vous pouvez encore ouvrir, changez de canal dont la frontière de calcul est écrite. Ouvrez le chiffrement de fichier, choisissez un canari jetable, et nommez-le canary-fp-20260922-vendor-key.txt. Gardez la phrase secrète sur cet ordinateur. Ouvrez Network, cochez Preserve log, et chiffrez. La ligne de requête et le corps ne doivent pas contenir le contenu du fichier, la phrase secrète, ni le nom de fichier complet comme champ métier. La sortie est .lock ou .enc. Un fichier est plafonné à 5 Go. Déchiffrez sur cette machine avec la même phrase secrète. Le canari doit revenir. Vous l’ouvrez parce que la phrase secrète est dans vos mains, pas parce que le nom de l’algorithme contient AES.

La cinquième étape ne demande pas au chiffrement de fichier de remplacer un client de programmation. Elle donne un contraste. La même phrase, « chiffré sur cette machine », peut vouloir dire que la dérivation de clé et AES-256-GCM restent dans l’onglet courant, et que le fichier et la phrase secrète ne sont pas envoyés comme données métier. Vous emportez le texte chiffré, et vous l’ouvrez. Une note précédente couvrait une autre couche : HTTPS ne protège que le saut jusqu’à un routeur. La couche en plus ici est qui ouvre l’enveloppe une fois le texte chiffré parti.

N’envoyez pas la phrase secrète complète et le texte chiffré dans le même fil. Un .lock du chiffrement de fichier peut être copié vers un disque. La phrase secrète doit voyager sur un canal que vous avez déjà vérifié, ou une courte phrase secrète peut siéger après # sur un lien auto-destructeur. Collez la clé et le cadenas dans le même message, et l’enveloppe a déjà disparu pour quiconque voit ce message.

Trois lectures excessives du « chiffrement local »

La première consiste à lire « AES a été appelé sur cette machine » comme « seul moi peux déchiffrer ». Un appel local dit seulement que le clair était encore sur cet ordinateur pendant l’empaquetage. Quand la clé publique vient du serveur et que la clé privée n’atterrit pas, le droit de déchiffrer siège dans le cloud. La liste d’algorithmes, la longueur de clé, et CTR face à GCM ne répondent pas à la question de savoir quel processus tient la clé privée.

La deuxième consiste à lire « envoyé droit vers le stockage objet, sans passer par le serveur d’application » comme « l’éditeur ne peut pas voir ». Le fichier peut sauter le serveur d’application. Le rappel d’enregistrement et la clé privée siègent encore du côté de l’éditeur. Sauter la salle d’application réduit une copie en clair dans les journaux d’application. Cela ne déplace pas le droit de déchiffrer. La note sur le routeur a montré que HTTPS n’arrête pas un proxy de couche applicative. Ce que cette note n’arrête pas, c’est l’extrémité qui tient la clé privée.

La troisième consiste à lire « détruit tout de suite / code ouvert / le seau est vide » comme « jamais collecté ». La destruction réduit la conservation. Le code ouvert vous laisse contrôler l’arbre public maintenant. Un seau vide veut dire qu’il n’y avait pas d’objet au moment de l’évaluation. Aucun de ces faits ne signifie automatiquement que des objets historiques n’ont jamais été ouverts, ni que les interrupteurs d’alors couvraient un historique Git complet. Ce qui appartient à une note de passation, c’est si cette machine génère encore une archive en attente, et si vous pouvez ouvrir le texte chiffré que vous êtes sur le point d’envoyer. Un titre qui dit que le problème a été corrigé n’est pas cette note.

Questions fréquentes

Si le fichier sur le disque est déjà du texte chiffré, est-ce du zéro connaissance local ?

Non. Le texte chiffré dit seulement que les octets empaquetés ne sont pas un espace de travail en clair. Si la clé publique RSA qui enveloppe la clé de contenu est émise par le serveur sur le moment, et si la clé privée correspondante n’atterrit jamais sur la machine, ni vous ni le client n’ouvrez le fichier. Cette enveloppe est faite pour que le cloud la lise, pas pour une sauvegarde que vous restaurez.

L’éditeur dit que les envois sont détruits tout de suite. Que pouvez-vous encore contrôler ?

« Détruire tout de suite » réduit la durée pendant laquelle un objet est gardé. Cela ne répond pas à la question de savoir si le premier paquet dépassait l’interrupteur que vous avez cliqué, ni qui tenait la clé privée avant la suppression. Un seau vidé après coup ne montre pas qui a déchiffré ou copié des objets déjà acceptés avant le 18 septembre.

Si je coupe « améliorer l’expérience » et « index du dépôt », l’envoi s’arrête-t-il aussi ?

Dans le client qui a été démonté, ces deux interrupteurs réglaient l’usage pour l’entraînement et le fait que le cloud construise un index. Aucun des deux ne coupait l’empaquetage ni l’envoi direct. Cherchez un réglage distinct qui arrête la génération d’instantanés, et vérifiez si un nouveau texte chiffré en attente apparaît encore en local après avoir coupé les autres.

Comment remettre à un collègue un fichier que je peux encore ouvrir ?

Chiffrez dans l’onglet courant avec AES-256-GCM, et ne donnez la phrase secrète qu’à un destinataire déjà vérifié. Ouvrez le chiffrement de fichier. Un fichier est plafonné à 5 Go. La sortie est .lock ou .enc. Le fichier et la phrase secrète ne sont pas envoyés par défaut. Prêt à l’emploi — aucun compte. Pour un court secret, utilisez Burn-Link et placez la clé après #. La forme du lien est s.html?id={id}#{key}. Si un ticket ou un journal porte encore un numéro de téléphone ou un numéro de pièce, faites d’abord un masquage par règles dans le nettoyage de confidentialité. Le texte source n’est pas envoyé comme donnée métier.

Quand vous devez pouvoir l’ouvrir, passez par un canal prêt à l’emploi

Si vous voulez une page qui écrit la frontière de calcul à découvert, et vous exercer à « j’ouvre le texte chiffré, et la phrase secrète n’entre pas dans Network », ouvrez le chiffrement de fichier de FastPwd. Aucune inscription. Choisissez le canari ci-dessus et lancez AES-256-GCM dans l’onglet courant, puis suivez les contrôles de la section précédente : la requête ne doit pas contenir le contenu du fichier ni la phrase secrète, et la même phrase secrète doit restaurer le fichier sur cette machine. Vous pouvez copier le .lock ou le .enc vers un disque. N’écrivez pas la phrase secrète dans le même fil, et ne la collez pas dans une boîte d’IA.

Quand vous devez encore remettre un extrait de dépôt à un modèle cloud, supposez que l’extrémité qui reçoit voit le texte entier que vous collez. Un routeur laisse un paquet d’appel en clair là où HTTPS s’arrête. La note précédente l’a déjà couvert. Cette note ajoute une question : si le client « chiffre » puis envoie, la clé privée qui ouvre l’enveloppe est-elle de votre côté ? Si les deux couches échouent, ne placez pas une clé cloud encore active, une clé privée SSH, ni des données client dans un espace de travail pour le remettre ensuite à un outil qui l’empaquete. Le masquage par règles peut couvrir des champs courants. Une clé entière doit passer par Burn-Link, ou ne pas partir du tout.

La prochaine fois qu’une note dira « nous chiffrons en local, puis nous envoyons », retenez trois choses. D’abord, demandez qui tient la clé privée ou la phrase secrète. Ne vous arrêtez pas au nom de l’algorithme. Ensuite, demandez si le manifeste couvre un historique .git qui n’est pas les fichiers courants. Enfin, comparez à un texte chiffré que vous ouvrez vous-même, pas à une déclaration de destruction. Ces trois phrases sont ce que vous pouvez écrire dans une note de passation. « C’est du texte chiffré sur le disque, donc le cloud ne le voit pas » n’en est pas une.

Pour aller plus loin

Un mot de passe sur une archive avant un envoi cloud ne cache pas les noms de fichiers, et ce n’est pas de l’AES-GCM local. Voir Ce qu’un mot de passe ZIP bloque avant un envoi dans le cloud, et pourquoi ce n’est pas de l’AES-GCM local. HTTPS ne chiffre que le saut jusqu’à un routeur, et il n’arrête pas une clé SSH dans une invite. Voir Pourquoi des clés SSH apparaissent dans un dump de 6 To d’un routeur LLM, et quelle couche HTTPS ne protège pas. Pour contrôler vous-même une page qui dit « chiffrement local » face à Network, voir Vérifier que le chiffrement local n’envoie pas le texte en clair.