Opciones de proxy del módulo Go y qué es lo que verifica realmente GOPROXY

Ya están disponibles los parches de php2shell (CVE-2026-109618 y CVE-2026-109619) para PHP en fin de vida útil. Dado que las respuestas del departamento de ventas están tardando más de lo habitual debido a la elevada demanda, la forma más rápida de obtener los paquetes parcheados es comprar ELS para Runtimes en línea (se abre en una pestaña nueva). Lee las preguntas frecuentes sobre los parches

Ir directamente al resumen generado por IA de esta entrada del blog

  • Resume esta entrada con Perplexity
  • Resume esta publicación con Gemini

Principales conclusiones

  • Un proxy del módulo Go está diseñado para servir archivos, no para determinar si es seguro ejecutarlos.
  • Un carácter de la cadena GOPROXY determina si un proxy inactivo falla de forma evidente o envía las compilaciones de forma silenciosa a la red pública de Internet.
  • GOPRIVATE omite la base de datos pública de sumas de comprobación para cada ruta que coincide, por lo que un patrón amplio puede desactivar esa protección en un ámbito mucho más amplio de lo previsto.

En mayo de 2026, los investigadores detectaron una oleada de módulos Go maliciosos publicados en una cuenta de GitHub llamada BufferZoneCorp. El robo de credenciales formaba parte de la carga útil, pero lo más interesante era el objetivo de varios de esos módulos de Go: el propio mecanismo de compilación. Corrompieron GOPROXY, debilitaron la verificación de la suma de comprobación, modificaron el archivo go.sum e introdujeron envoltorios falsos de Go en las rutas del flujo de trabajo, de modo que los pasos posteriores de la integración continua (CI) ejecutaran el binario del atacante en lugar de la cadena de herramientas real. El equipo de seguridad de Go bloqueó los módulos identificados. La técnica sigue funcionando en cualquier lugar donde la estructura de módulos se trate como una configuración en lugar de como un límite de seguridad.

El almacenamiento en caché dota a esa infraestructura de una gran memoria. Un módulo puede seguir siendo accesible mucho después de que su código fuente haya cambiado o desaparecido, y una brecha de seguridad anterior en Go demostró hasta dónde llega esto: el proxy público de módulos de Go siguió sirviendo una versión maliciosa durante más de tres años después de que la etiqueta correspondiente de GitHub se hubiera reescrito discretamente (más detalles al respecto a continuación). Ese problema de persistencia es una de las principales razones por las que los equipos ponen en marcha un proxy de módulos interno y configuran GOPROXY para que apunte a él.

El instinto no se equivoca. Mejora la reproducibilidad de la compilación, las dependencias almacenadas en caché dejan de depender de que se pueda acceder al proxy público y, por fin, hay un único lugar donde ver de qué depende la organización.

Lo que no se deduce es la conclusión sobre la seguridad. Un proxy de módulos sirve bytes. El protocolo en sí mismo no incluye ningún paso de verificación de contenido ni ningún mecanismo de políticas, y no emite ningún juicio sobre el contenido de los archivos que devuelve. Gestionar tu propio proxy implica controlar la caché, lo cual es útil, pero no es lo mismo que controlar lo que entra en ella.

Qué hace realmente un proxy del módulo Go

El protocolo del módulo proxy es deliberadamente sencillo. Un proxy es un servidor HTTP que expone unos pocos puntos de conexión por cada ruta de módulo:

Punto final Devoluciones
$module/@v/list Versiones conocidas, una por línea
módulo/@v/versión.info Metadatos JSON, incluida la marca de tiempo de la versión
módulo/@v/versión.mod El archivo go.mod de esa versión
módulo/@v/versión.zip El archivo fuente del módulo
$module/@latest La versión que el proxy considera más reciente

 

Eso es todo lo que hay. Nada de lo que figura en esa lista incluye una firma, el resultado de un análisis, una valoración de la política de seguridad ni ninguna afirmación verificable sobre el origen del código.

Nota: Dado que el protocolo consiste en solicitudes HTTP GET simples sobre una estructura de rutas predecible, un directorio de archivos servidos por NGINX cumple técnicamente los requisitos para ser un proxy válido de módulos de Go. Esa es una de las razones por las que los proxies se han extendido tan rápido en el mundo de Go, y también por las que tan pocos de ellos realizan verificaciones, a menos que tú mismo las incorpores.

La verificación en Go se lleva a cabo en el lado del cliente, no en el proxy. El comando «go» compara el contenido del módulo descargado con el hash de go.sum. Cuando ese hash aún no está registrado, normalmente lo obtiene de la base de datos de sumas de comprobación —un registro independiente de solo adición— antes de escribirlo en go.sum. Una vez registrado, las compilaciones posteriores simplemente lo comparan con ese hash almacenado.

Así pues, las propiedades de seguridad que la mayoría de los equipos atribuyen a su proxy son, en realidad, propiedades de go.sum y GOSUMDB. Estas funcionan exactamente igual tanto si se ejecuta un proxy como si se accede a proxy.golang.org directamente.

La coma y la barra vertical determinan el comportamiento por defecto

GOPROXY toma una lista de fuentes, y el carácter que las separa determina qué ocurre cuando una de esas fuentes falla.

# Pasa a la siguiente entrada solo en caso de error 404 o 410

GOPROXY=https://goproxy.internal.example.com,direct

 

# Pasa a la siguiente entrada ante CUALQUIER error

GOPROXY=https://goproxy.internal.example.com|direct

Ese diagrama da por hecho que «direct» es la siguiente fuente de la lista, tal y como se muestra en los ejemplos anteriores. Por sí sola, una barra vertical solo significa que se pasa a lo que venga a continuación.

Una coma indica al comando `go` que pruebe la siguiente fuente solo cuando la actual informe de forma inequívoca que el módulo no existe, es decir, que devuelva un error 404 o 410. Una barra vertical le indica que pruebe la siguiente fuente ante cualquier error, incluidos los tiempos de espera agotados, los fallos de TLS y los errores 500.

Imagina lo que eso significa en pleno incidente. Tu proxy interno tiene un problema de implementación y empieza a devolver errores 502. Con una configuración «pipe» seguida de «direct», todas las compilaciones de la organización empiezan, sin que nadie se dé cuenta, a resolver los módulos desde el control de versiones público.

Separador Se queda en nada en Comportamiento cuando el servidor proxy no está disponible
Coma Solo 404 y 410 Otros errores de proxy impiden la resolución, por lo que las compilaciones fallan de forma evidente
Tubo Cualquier error Resolution pasa a la siguiente fuente, por lo que una conexión directa posterior elude silenciosamente el proxy.

 

Consejo profesional: Fíjate en lo que realmente tiene configurado tu CI, no en lo que el manual de procedimientos indica que tiene configurado. Los parámetros GOFLAGS y GOPROXY suelen heredarse de las imágenes base, y una tubería que alguien añadió hace dos años para solucionar un problema en una implementación inestable es exactamente el tipo de cosa que sobrevive a todas las revisiones posteriores, porque las compilaciones siguen dando resultado positivo.

La opción «direct» que aparece al final de la mayoría de las cadenas de GOPROXY también merece una atención especial. Indica a la cadena de herramientas que recurra al control de versiones cuando el proxy no encuentre nada, de modo que una ruta de módulo que tu proxy nunca haya visto se resuelva directamente desde su repositorio de origen, como de costumbre. Si el objetivo principal de poner en marcha un proxy era que fuera la única fuente de verdad, la opción «direct» anula silenciosamente ese propósito.

GOPROXY=off es la opción más estricta que existe. El comando «go» no descargará ningún módulo, por lo que todo lo que necesite la compilación debe estar ya en la caché de módulos. Si se omite la ruta directa al final, se obtiene un límite estricto de fuentes sin llegar a ir tan lejos.

Por qué el autoalojamiento no verifica nada por sí mismo

Atenas es un programa muy fiable. Hace exactamente lo que se espera de un módulo proxy.

Lo que no incluye es ninguna indicación sobre el contenido de un módulo. No hay ningún análisis de malware integrado, ni comprobación de que el archivo coincida con su repositorio de origen, ni ninguna forma predeterminada de indicar «bloquea este módulo, ha empezado a hacer algo nuevo en la versión 1.4.2». El filtrado estándar funciona en función de las rutas de los módulos, en lugar de basarse en lo que el código esté haciendo. Athens sí que ofrece un gancho de validación que se invoca cada vez que se descarga un módulo, de modo que los operadores pueden ampliarlo con su propio análisis o lógica de políticas, pero esa verificación es algo que tú mismo debes diseñar, ejecutar y mantener en funcionamiento.

Esa brecha es importante debido al lugar en el que se ejecuta el código malicioso de Go. Go no cuenta con un script de instalación que se ejecute en el momento de la instalación, como npm , lo cual es un verdadero punto a su favor. Sin embargo, el código malicioso de un módulo de Go se ejecuta posteriormente, cuando se ejecuta una aplicación o herramienta que importa el paquete, normalmente a través de una función init() que se activa durante el inicio del programa.

Un proxy que almacena en caché y sirve ese módulo no ha hecho nada incorrecto según la especificación. Ha cumplido exactamente la función para la que fue diseñado.

La verdadera incongruencia radica en si el archivo que entrega un proxy coincide con el repositorio de origen al que, según su ruta de módulo, pretende apuntar. Nada en el protocolo exige que el archivo ZIP de un módulo se corresponda con ninguna confirmación concreta, lo que lo convierte en un artefacto más que en una certificación. Recompilar un módulo a partir del código fuente y comparar ese resultado con lo que se ha servido a través de la ruta es un control distinto, y debe realizarse antes de que el artefacto sea admitido en un almacén de confianza o se sirva a una compilación.

Comparativa de cinco arquitecturas GOPROXY

Cinco jugadas cubren prácticamente todo lo que los equipos practican en los entrenamientos. Lo que las diferencia es qué jugador hace la pantalla en cada una y quién se encarga de ejecutarla.

Arquitectura Control de disponibilidad Muestra el contenido del módulo Carga operativa
Directamente de VCS Ninguno, depende del servidor de origen No Ninguno
Proxy público con alternativa directa La caché de Google y VCS No Ninguno
Proxies autohospedados, como Athens Tú controlas la caché No de forma predeterminada Moderador, te toca a ti dirigirlo
Proxy del gestor de repositorios Tú controlas la caché, además de las reglas de política Varía según el producto y los complementos Moderado
Registro revisado y reconstruido Tú controlas la caché Sí Low, a tu servicio

 

El proxy público con recurso alternativo directo es la opción predeterminada con la que empiezan la mayoría de los equipos, y es mejor de lo que se dice de él. proxy.golang.org mantiene una caché inmutable, por lo que una versión que haya servido una vez permanece disponible y sin cambios, incluso si se elimina el repositorio de origen. Esa es una propiedad de seguridad real, y el autoalojamiento no la reproduce automáticamente.

Muchos equipos acaban optando por un proxy autohospedado como Athens, y la conclusión sincera es que lo que ofrece es disponibilidad y visibilidad, más que verificación.

Un proxy de gestión de repositorios añade un control de acceso centralizado y, en función del producto y de los complementos de políticas que se hayan adquirido, puede auditar los componentes para comprobar que cumplen con las políticas y poner en cuarentena aquellos que no lo hagan. Lo que el proxy convencional aún no garantiza es que un artefacto se haya recompilado a partir de la fuente que indica su ruta y que, efectivamente, se corresponda con ella.

Un registro filtrado y reconstruido constituye una categoría distinta, más que una variante de las cuatro primeras. Reconstruye cada módulo a partir del código fuente y lo analiza en busca de malware antes de servirlo, razón por la cual es la única fila que responde «sí» en la columna de filtrado. Ese es el modelo SecureChain para Go , cuya cobertura para Go está prevista para el cuarto trimestre de 2026.

De dónde proviene el uso indebido de la caché del proxy

Los incidentes relacionados con la caché que afectan a la infraestructura de los módulos de Go suelen seguir un patrón similar, y uno ocurrido a principios de 2025 lo ilustra muy bien. En febrero de ese año, unos investigadores descubrieron un módulo llamado github.com/boltdb-go/bolt que se hacía pasar por BoltDB, un almacén de clave-valor integrado muy utilizado que contaba con más de 8.000 paquetes dependientes cuando se notificó el incidente.

El autor de la amenaza había publicado la versión maliciosa ya en noviembre de 2021; posteriormente, reescribió la etiqueta de GitHub para que apuntara a una confirmación limpia, lo que significaba que cualquiera que revisara el repositorio manualmente no detectaría nada sospechoso. El proxy del módulo Go ya había almacenado en caché la versión maliciosa original y, dado que dicha caché está diseñada para ser inmutable, la copia con puerta trasera permaneció disponible durante más de tres años para cualquier cliente que solicitara esa versión del módulo, hasta que los investigadores finalmente la señalaron como un «typosquat».

No se trató de un error de suma de comprobación. «boltdb-go/bolt» era una ruta de módulo distinta que se hacía pasar por otra, por lo que no existía una suma de comprobación fiable del BoltDB auténtico con la que tuviera que coincidir el falso. Las comprobaciones de integridad de Go no tuvieron ningún problema en autenticar los propios bytes del «typosquat», ya que esa es precisamente la cuestión que evalúan. La puerta trasera tuvo éxito en cuanto al nombre.

Esa distinción es importante, porque no es lo mismo que la confianza ciega desde el primer uso. En el caso de los módulos públicos, el cliente suele consultar la base de datos de sumas de comprobación —un registro autenticado de forma independiente— la primera vez que necesita un hash para una versión, por lo que un proxy no puede modificar unilateralmente el valor de confianza de una versión que ya está registrada. Un proxy autohospedado sigue decidiendo qué artefacto ve primero el cliente, pero con GOSUMDB instalado es la base de datos de sumas de comprobación, y no el proxy, la que decide si ese artefacto es aceptado.

Lo que nada de eso hace es comprobar si un módulo es digno de confianza en primer lugar, que es precisamente la brecha por la que se cuela un «typosquat». Y la parte pública del mismo se desactiva ante cualquier elemento coincidente con GOPRIVATE, o en cualquier entorno en el que GOSUMDB esté desactivado.

Escenario Las comprobaciones de integridad de Go lo detectan
La versión almacenada en caché se modifica posteriormente in situ Sí, discrepancia en go.sum
Primera resolución de un módulo público a través de un proxy comprometido Normalmente sí, si GOSUMDB está activado y dispone de un registro para esa versión, o puede obtenerlo.
Ruta del módulo que coincide con un patrón GOPRIVATE En parte, la consulta a la base de datos pública se omite por defecto, aunque una entrada existente en go.sum sigue detectando cualquier manipulación posterior.
El servidor proxy ofrece una versión pública que el servidor de origen nunca publicó Sí, en los casos en que se aplique la verificación mediante la suma de comprobación de la base de datos, ya que la base de datos no puede autenticar una versión que no existe en el origen.

 

Lo que GOPRIVATE desactiva discretamente

GOPRIVATE existe por una buena razón. Los módulos privados no deberían solicitarse a un proxy público, y sus rutas tampoco deberían enviarse a una base de datos pública de sumas de comprobación, ya que la propia ruta del módulo puede revelar información sobre lo que estás compilando.

También es una variable de conveniencia, y el efecto secundario es lo que hace que las cosas se tuerzan. GOPRIVATE proporciona el valor por defecto tanto para GONOPROXY como para GONOSUMDB, según la referencia de módulos de Go, lo que significa que cada ruta con la que coincida queda excluida del proxy y de la base de datos pública de sumas de comprobación al mismo tiempo, a menos que se configure por separado una de esas dos variables.

Aquí es donde eso falla en la práctica.

GOPRIVATE=github.com/yourcompany/*

Si lo acotas lo suficiente, coincidirá con la organización con la que querías coincidir.

GOPRIVATE=*.example.com,github.com/*

Ese segundo patrón excluye de la base de datos pública de sumas de comprobación todos los módulos alojados en GitHub, lo que abarca una parte enorme de lo que se descarga en la mayoría de las compilaciones de Go. Es fácil que los patrones se amplíen de esta manera: hay que solucionar un error de resolución y, al relajar la coincidencia, la compilación pasa a verde de inmediato.

Comprueba qué configuraciones tienen realmente tus entornos:

go env GOPROXY GOSUMDB GOPRIVATE GONOPROXY GONOSUMDB GOFLAGS

Ejecuta eso en un servidor de integración continua, no solo en tu portátil. Puede haber diferencias entre ambos, ya que la integración continua toma las variables de las imágenes base y de la configuración del servidor.

Configúralos de forma deliberada. Configura GONOPROXY y GONOSUMDB directamente cuando tu enrutamiento y tu política de sumas de comprobación deban diferir, lo cual ocurre con más frecuencia de lo que los equipos esperan. Si un proxy interno de confianza da servicio tanto a módulos públicos como privados, GONOPROXY=none hace que todo siga pasando por ese proxy, mientras que GONOSUMDB solo cubre las rutas que son verdaderamente privadas. Lo que no conviene es lo contrario, es decir, dejar que las rutas privadas aparezcan en la consulta de la base de datos pública, lo que o bien interrumpe la compilación o bien filtra la ruta a un servicio público.

Elegir una arquitectura

La decisión depende, en definitiva, del problema que realmente estés intentando resolver, y ser sincero al respecto acorta considerablemente la duración de todo el proyecto.

Si el motivo es la disponibilidad y la reproducibilidad de la compilación, utiliza un proxy autohospedado o un gestor de repositorios, emplea una coma en lugar de una barra vertical y deja de llamarlo «control de seguridad». Se trata de una buena infraestructura que cumple exactamente con la función para la que fue diseñada. Si el motivo es la visibilidad de aquello de lo que depende la organización, casi cualquier proxy te permite conseguirlo, y las opciones de los gestores de repositorios ofrecen mejores informes con menos carga operativa.

Si el motor es la aplicación de políticas sobre qué módulos están permitidos, un gestor de repositorios con reglas de ruta constituye la base, y es en sus complementos de políticas o cortafuegos donde realmente se lleva a cabo la aplicación. Athens puede orientarse en esa dirección a través de su gancho de validación, pero tú eres el responsable de la lógica, el ajuste y el sistema de alertas.

Si el controlador está verificando que el contenido del módulo es fiable, el protocolo del proxy por sí solo no da respuesta a esa cuestión, ya que nunca se diseñó con un paso de verificación. Ese control debe situarse en torno al proxy o proceder de un sistema que valide los artefactos comparándolos con el código fuente antes de servirlos.

Y si Go forma parte de tu pila junto con npm, PyPI, Maven o crates.io, decide la arquitectura una sola vez para todos ellos. Cinco proxies por ecosistema gestionados por cinco equipos diferentes son precisamente la causa de que surjan lagunas en la cobertura. PolinRider es un buen ejemplo de por qué esto es así: la campaña vinculada a Corea del Norte que se ha rastreado bajo ese nombre ha estado publicando paquetes maliciosos en npm, Packagist, módulos de Go y extensiones de Chrome, y seguía activa cuando los investigadores publicaron su informe en julio de 2026. El clúster más amplio «Contagious Interview», al que pertenece, se ha relacionado con más de 1.700 paquetes maliciosos en npm, PyPI, Go y Rust. Un problema a nivel de pila requiere una solución a nivel de pila, no cinco cachés inconexas.

Un proxy es el lugar adecuado para resolver cuestiones de disponibilidad, latencia y reproducibilidad. Sin embargo, no es el lugar adecuado para abordar cuestiones de confianza. Mantener estos dos objetivos separados permite que la arquitectura sea sencilla y que se pueda lanzar un proxy que funcione. Mezclarlos convierte un proyecto sencillo de almacenamiento en caché en un esfuerzo mucho mayor de ingeniería de políticas y seguridad, con el riesgo real de acabar con una capa de políticas compleja acoplada a lo que, en esencia, es un componente de almacenamiento en caché.

Dónde encaja TuxCare SecureChain

También hay un problema que ningún proxy aborda: los módulos que ya nadie mantiene. Una caché sirve un módulo inactivo con la misma fidelidad que uno que se mantiene activamente, y un módulo sin parches, con un CVE conocido y sin corrección por parte del desarrollador original, no es algo que resuelva una arquitectura de caché. La retroaplicación de una corrección a código del que el mantenedor se ha desentendido es una disciplina en sí misma, basada en pruebas de regresión y compatibilidad de comportamiento, lo que suele ser la razón por la que acaba quedando fuera del ámbito de competencia de un equipo de plataforma.

Si lo que le falta a tu arquitectura es la verificación, ahí está la laguna SecureChain se ha creado para subsanarla en todos los ecosistemas que suelen formar parte de la misma pila. npm ya está disponible, Maven y PyPI llegarán en agosto de 2026, y Go, Rust/crates.ioy Packagist/PHP les seguirán en el cuarto trimestre de 2026. En cada uno de ellos, SecureChain recompila los paquetes desde el código fuente, los revisa en el momento de la descarga antes de que nada llegue a la compilación y sigue aplicando parches a las vulnerabilidades conocidas incluso después de que el desarrollador original del paquete haya dejado de ofrecer soporte. ¿Te preguntas cómo encaja esto en tu propia configuración de GOPROXY o en el resto de tu pila de aplicaciones? Haznos una pregunta y el equipo te lo explicará paso a paso.

PREGUNTAS FRECUENTES

¿Qué es un proxy de módulo de Go?

Un servidor HTTP que implementa el protocolo de proxy de módulos de Go. Proporciona listas de versiones, metadatos, archivos «go.mod» y archivos fuente para las rutas de los módulos. Almacena en caché y redirige, y el protocolo en sí no incluye ninguna verificación del contenido que devuelve.

¿El hecho de ejecutar mi propio proxy de módulos Go hace que las compilaciones sean más seguras?

Mejora la disponibilidad, la reproducibilidad y la visibilidad, aspectos todos ellos muy útiles. El protocolo proxy no cuenta con un paso de verificación propio. La autenticación del contenido se lleva a cabo en el lado del cliente: el comando «go» comprueba las descargas con go.sum y, en el caso de los módulos públicos, con la base de datos de sumas de comprobación cuando aún no se ha registrado ningún hash. Esto funciona igual tanto si se está ejecutando un proxy como si no, a menos que GOSUMDB esté desactivado o que la ruta esté excluida de la base de datos pública mediante GOPRIVATE o GONOSUMDB.

¿Cuál es la diferencia entre una coma y una barra vertical en GOPROXY?

Una coma hace que el comando «go» pase al siguiente código fuente únicamente en caso de error 404 o 410, por lo que cualquier otro error del proxy detiene la resolución. Una barra vertical hace que pase al siguiente código fuente ante cualquier error, lo que significa que una interrupción del proxy puede enviar silenciosamente las compilaciones a la red pública de Internet en lugar de simplemente fallar.

¿Desactiva GOPRIVATE la verificación de la suma de comprobación?

Por defecto, omite la consulta a la base de datos pública de sumas de comprobación para las rutas coincidentes, ya que GOPRIVATE alimenta GONOSUMDB. Una entrada existente en go.sum puede detectar un cambio posterior en el contenido.

¿Es suficiente Atenas para un proxy privado del módulo Go?

En cuanto a la disponibilidad, el almacenamiento en caché y la distribución interna de módulos, sí. Su filtrado estándar se basa en las rutas de los módulos en lugar de en el contenido, por lo que, tal y como viene de fábrica, no te indicará si un módulo es malicioso ni si el archivo que está sirviendo coincide con su repositorio de origen. Su gancho de validación se puede ampliar con ese tipo de lógica, pero esa parte la diseñas y gestionas tú mismo.

¿Cómo puedo comprobar en qué confían realmente mis compilaciones de Go?

Ejecuta «go env GOPROXY GOSUMDB GOPRIVATE GONOPROXY GONOSUMDB GOFLAGS» en un ejecutor de CI. La configuración heredada de las imágenes base y los ajustes del ejecutor suelen diferir de las configuraciones locales de desarrollo y de lo que indique el runbook.

 

Resumen
Opciones de proxy del módulo Go y qué es lo que verifica realmente GOPROXY
Nombre del artículo
Opciones de proxy del módulo Go y qué es lo que verifica realmente GOPROXY
Descripción
Un proxy de módulos de Go almacena en caché y redirige, y el protocolo no verifica nada sobre el contenido del módulo. Depende de lo que decidan GOPROXY, GOPRIVATE y la base de datos de sumas de comprobación.
Autor
Nombre del editor
TuxCare
Logotipo de la editorial

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.

Índice
Obtenga las respuestas de seguridad de código abierto que necesita

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.