ZCode empaquetaba tu historial Git completo y lo subía cifrado a la nube: la llave nunca fue tuya

ZCode empaquetaba tu historial Git completo y lo subía cifrado a la nube: la llave nunca fue tuya

ZCode empaquetaba tu historial Git completo y lo subía cifrado a la nube: la llave nunca fue tuya

Esta semana apareció en Hacker News una investigación que me dejó helado, y lo peor es que no necesita cero-days ni malware: solo un desktop app de IA que hace exactamente lo que le programaron hacer. Un desarrollador que firma como ferstar se puso a revisar por qué su carpeta ~/.zcode pesaba más de 700MB, y terminó reconstruyendo, vía ingeniería inversa del app.asar, un flujo completo de exfiltración de su propio código fuente.

Lo que encontró dentro del paquete

ZCode, la app de escritorio oficial de Zhipu (la empresa detrás de GLM), escaneaba su workspace activo —un proyecto comercial, ojo— y lo empaquetaba completo: historial .git, caché de LFS, reflogs y configuraciones globales. Del repo total de 10GB, quedaban 345MB después de excluir node_modules, y casi el 90% del snapshot era pura propiedad intelectual: el historial de commits con todos sus secretos. Lo comprimía a 313MB, lo cifraba con AES-256-CTR, envolvía la llave simétrica con RSA-OAEP, y lo subía directo a un bucket de Aliyun OSS. Un detalle miserable: el archivo de estado mostraba 564 intentos de subida fallidos. No era un bug puntual; era una cola insistente esperando su oportunidad.

La ironía criptográfica

Acá está lo que más me gustó del hallazgo, porque es una lección de seguridad aplicada: el cifrado envelope era de libro de texto, impecable técnicamente. Pero la llave pública RSA la entregaba el servidor durante la negociación de credenciales, y la llave privada nunca tocaba tu máquina. Resultado: ese ciphertext de 313MB tirado en tu propio disco no lo puede abrir ni tú ni el propio cliente. Solo el backend de Zhipu tiene la llave.

Ferstar lo dice sin rodeos y yo lo firmo: si esto fuera sync entre dispositivos o rollback para el usuario, las llaves vivirían localmente, como hace Git o Time Machine. Una llave que solo el servidor puede usar sirve exactamente para una cosa: garantizar que el servidor pueda leer tu código cuando se le antoje. Es la diferencia entre respaldo y vigilancia, escrita en criptografía.

Los switches no detenían nada

Otra perla: los toggles de privacidad en la interfaz no frenaban la subida. El empaquetado y la cola de envío seguían corriendo de todas formas. Y en los snapshots de 42.411 archivos, casi el 90% del contenido era .git. Si alguna vez pensaste que un commit con credenciales hardcodeadas que ya «limpiaste» era agua pasada, esta historia te recalibra la cabeza: tu historial completo viajó a un bucket en Alibaba Cloud sin que apretaras nada.

La defensa es ridículamente simple

La contramedida que propone es un one-liner: en macOS, sudo touch ~/.zcode && sudo chflags uchg ~/.zcode; en Linux, touch ~/.zcode && chattr +i ~/.zcode. Un archivo inmutable con ese nombre bloquea que la app cree su directorio de datos. Y para lo que ya quedó en el disco, borralo; aunque con cifrado server-side el borrado local es apenas un whack-a-mole si el proceso se reinicia.

Mi opinión: es un cambio de era

Lo que me preocupa no es ZCode específicamente, es el patrón. Estamos instalando apps de IA con los mismos permisos que le daríamos a un estagiario con acceso root, confiando en que el desktop app «solo hace lo que dice la UI». Ferstar hizo lo que cualquier ingeniero de sistemas debiera hacer con una caja negra que consume 700MB de su disco: abrirla. Y encontró que la caja era un tubo hacia la nube de otra empresa.

Yo trabajo todos los días con agentes de código y no pienso dejar de hacerlo. Pero esta historia confirma una regla que me estoy tomando cada vez más en serio: antes de loguearte en cualquier app de IA nueva con tu código de trabajo, revisa qué conecta y qué cifra. Si la llave de cifrado viene del servidor, no hay confidencialidad, hay cortesía. Y en la pega, la cortesía no te protege de un NDA roto.

Si usas herramientas de este tipo en proyectos comerciales, hazle el mismo ejercicio de ferstar: mira qué pesa tu carpeta de config, revisa las conexiones activas del proceso, y pregúntate por qué una app de coding necesita mantener sesiones persistentes con nodos de almacenamiento en la nube. La respuesta, cuando existe, casi nunca es buena.

Fuente de inspiración: Inside ZCode: Silently Uploading Your Entire Git History to the Cloud

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *