Yeda AI Tips · #166

English

Los secretos borrados en una capa posterior de Docker siguen vivos en el historial

Borraste el .env de tu imagen de Docker. Sigue ahí adentro.

Una imagen de Docker no es un solo sistema de archivos: es una pila de capas de solo lectura, una por instrucción de construcción. Cada RUN, COPY y ADD agrega una capa nueva sobre la anterior. Cuando una capa posterior "borra" un archivo, solo escribe una marca de ocultamiento (whiteout) que lo esconde en la vista combinada. Los bytes de la capa anterior nunca se tocan. El secreto sigue ahí, a un comando de distancia de cualquiera que tenga la imagen.

Por qué "borrar" no elimina

Las capas son inmutables y direccionadas por contenido. Este Dockerfile parece seguro: copia un archivo de credenciales, lo usa y luego lo elimina:

COPY .env /app/.env
RUN some-tool --config /app/.env && rm /app/.env

El rm corre en la misma capa, así que la imagen combinada no muestra ningún .env. Pero si el secreto alguna vez se escribió en su propia capa (un COPY .env, un valor de ARG/ENV, o un archivo creado antes y borrado después), esa capa todavía lo contiene. Un whiteout en una capa más nueva lo esconde; no lo elimina.

ENV y el ARG de construcción son peores: sus valores se guardan en los metadatos de la imagen, legibles directamente desde docker history o docker inspect, sin necesidad de descomprimir nada.

Extraerlo toma un solo comando

No necesitas herramientas especiales. Guarda la imagen en un tarball y mira dentro:

docker save myimage:latest -o image.tar
tar -xf image.tar          # cada blob es el sistema de archivos de una capa

docker export (de un contenedor en ejecución) muestra la vista combinada, así que los archivos borrados parecen haber desaparecido. docker save exporta cada capa por separado, así que los archivos ocultos por whiteout reaparecen. Herramientas como dive muestran lo mismo de forma interactiva. Considera comprometida cualquier imagen que alguna vez haya tocado un secreto.

La solución: nunca grabes secretos en una capa

AntipatrónPor qué se filtraUsa en su lugar
COPY .env y luego rmla capa anterior conserva el archivoRUN --mount=type=secret
ARG TOKEN=... / ENV TOKEN=...queda en los metadatos de la imagenbuild secret mount
descargar clave, borrar en un RUN posteriorla capa anterior conserva la clavebuild secret o inyección en runtime

Los build secrets de BuildKit montan el valor dentro del contenedor de construcción solo durante esa única instrucción; nunca queda en una capa ni en los metadatos:

docker build --secret id=aws,src=$HOME/.aws/credentials .
RUN --mount=type=secret,id=aws \
    AWS_SHARED_CREDENTIALS_FILE=/run/secrets/aws \
    aws s3 cp ...

Para secretos que tu aplicación necesita en tiempo de ejecución (no de construcción), no los pongas en la imagen: inyéctalos en docker run mediante un gestor de secretos o un secret del orquestador, para que la imagen quede limpia.

Movidas avanzadas

Recursos

¿Desarrollas sistemas de IA o en la nube? Yeda AI audita y refuerza pipelines de LLM y contenedores en producción. Hablemos · Lee el blog