cisagov / cisagov/skeleton-docker

Cached security updates for Debian-based images

Open
#313 0 comments 0 reactions 0 assignees View on GitHub
dependencies docker improvement security upstream update
Dominant language
Shell
Stars
22
Forks
14
Avg merge
1d 18h
Merged PRs (30d)
4

Description

# 💡 Summary #

A technique for efficiently applying security updates to Debian-based images. Since this is currently an Alpine-based project it doesn't apply directly, but is a useful pattern none the less.

## Motivation and context ##

I added a vulnerability scanner to my build process that rejected images with high, or critical vulnerabilities. Since the Debian images are released less frequently I could not rely on them being fixed in a timely manner. I also didn't want to apply and rebuild the base image every time as this would invalidate much of the cache. This solution allows the application of the latest patches while preserving the cache.

https://github.com/felddy/foundryvtt-docker/blob/646856f295a4221ef5d1b7768d471112a47558f1/Dockerfile#L15-L38

It allows the use of less frequently released base images without suffering from unpatched vulnerabilities.

Perhaps there is an analog for Alpine-based images.

- https://stackoverflow.com/questions/70972914/how-to-upgrade-alpine-docker-base-images-for-security-patches

## Implementation notes ##

```Dockerfile
...
ARG NODE_MAJOR_VERSION=24
ARG DEBIAN_SUITE=trixie
ARG NODE_IMAGE_VERSION=${NODE_MAJOR_VERSION}-${DEBIAN_SUITE}-slim

# This stage exists solely to track the state of the Debian archives that carry
# security fixes. BuildKit revalidates remote ADD sources on every build and
# derives their cache key from the fetched content, so patched-base below - and
# everything downstream of it - is invalidated exactly when these archives are
# republished. Without this, the RUN in patched-base would be cached
# indefinitely and would silently stop applying new security updates.
#
# The InRelease files are architecture independent (~45 KB each) and are only
# bind-mounted, so nothing from this stage is committed to any image layer.
FROM scratch AS archive-state
ARG DEBIAN_SUITE
ADD https://deb.debian.org/debian-security/dists/${DEBIAN_SUITE}-security/InRelease /security
ADD https://deb.debian.org/debian/dists/${DEBIAN_SUITE}-updates/InRelease /updates

# Apply Debian security updates for every downstream stage. The upstream node
# image's Debian rootfs is built from the main archive only, so fixes published
# to -security are absent from it until a Debian point release folds
# them into main. This affects the shipped image and the stages that handle
# credentials and untrusted downloads alike.
FROM public.ecr.aws/docker/library/node:${NODE_IMAGE_VERSION} AS patched-base
RUN --mount=type=bind,from=archive-state,target=/run/archive-state \
apt-get update \
&& apt-get upgrade -y --with-new-pkgs \
&& rm -rf /var/lib/apt/lists/*
...
```

## Acceptance criteria ##

How do we know when this work is done?

- [ ] Builds a Debian-based image with cached security patches

Contributor guide

Open the contributing guide

Research direction

Start with the repository's existing Alpine-based Dockerfile and compare its image stages with the linked foundryvtt Dockerfile example. Determine whether a Debian-based build is intended here and verify that the finished build applies cached security patches, as required by the acceptance criterion.

Written by the indexing model from the issue text.

Assessment

Tech stack
debian, docker, dockerfile
Domain
devops, infrastructure, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.