Investigated Docker layer history in an OCI image archive to recover a database password deleted in a later build layer.
We're handed a file called layer_cake.tar from a fictional company called Noirtech, who helpfully reassure us that even though they sometimes put secrets in their Docker images, they removed them this time. The challenge description is basically a spoiler if you've been doing this long enough — but let's walk through it properly.
First, unpack the tar and see what we're dealing with:
This is an OCI image archive — the standard format produced by docker save. The manifest.json is the entry point.
Key findings from the manifest:
noirtech-recipes-challenge:latestblobs/sha256/6c7d365f50bf...The config blob contains the full Dockerfile history. This is where things get interesting:
The full layer map (condensed):
ADD alpine-minirootfs-3.18.12-x86_64.tar.gz /apk add bash curladduser appmkdir -p /opt/app/config /opt/app/logs ...COPY requirements.txt, main.py, models.py, routes.py...COPY production.env → /opt/app/config/production.env ← 🔑app.env (non-secret config)rm /opt/app/config/production.env ← the "fix"healthcheck.shproduction.env was added in layer 14, and then later deleted in layer 17. Because the file was committed to the image filesystem history in layer 14, deleting it later does not remove it from layer 14's tarball.
To retrieve the file, we can extract the layer 14 tarball directly:
# Noirtech Production Configuration
# !! DO NOT COMMIT — contains production secrets !!
APP_ENV=production
APP_SECRET_KEY=b3f2a1c8d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9
# Primary database
DB_HOST=db-primary.noirtech.internal
DB_PORT=5432
DB_NAME=noirtech_prod
DB_USER=noirtech_app
DB_PASSWORD=VFdWMFlVTlVSbnRrTUdOck0zSmZjbTFmWkRBemMyNTBYM0l6ZDNKcGRETmZhR2x6ZERCeWVYMD0K
Just for completeness, let's look at the deletion layer (17):
The zero-byte .wh.production.env file is a whiteout marker. The Docker union filesystem reads this and hides the file from the final running container, but does nothing to purge it from previous layers.
The DB_PASSWORD value in the production configuration was double-base64 encoded:
To prevent secrets leakages, Noirtech should employ one of the following methods:
RUN --mount=type=secret,id=prod_env,target=/opt/app/config/production.env python3 setup.py configure