Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
"ignorefile",
"imagetools",
"importlib",
"libc",
"libgnutls",
"liblua",
"ltrimstr",
"luacheck",
"luarocks",
"luassert",
"markdownlint",
"mediatype",
"mikefarah",
Expand Down
18 changes: 18 additions & 0 deletions images/ci-tools/.trivyignore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,21 @@ vulnerabilities:
so practical risk is negligible. Tracking: #96. Remove once both ship
builds on Go >= 1.25.11 or 1.26.4.
expired_at: 2026-07-21

- id: CVE-2026-32316
statement: >-
jq: DoS or potential arbitrary code execution via crafted input, fixed
in 1.6-2.1+deb12u2. Affects jq 1.6-2.1+deb12u1 — the deb12u2 build is
not yet in the Debian mirror, so a rebuild still installs deb12u1. jq
runs only on trusted CI inputs here, so practical risk is negligible.
Tracking: #96. Remove once deb12u2 reaches the bookworm mirror.
expired_at: 2026-08-19

- id: CVE-2026-40164
statement: >-
jq: DoS via a crafted JSON object, fixed in 1.6-2.1+deb12u2. Affects jq
1.6-2.1+deb12u1 — the deb12u2 build is not yet in the Debian mirror, so
a rebuild still installs deb12u1. jq runs only on trusted CI inputs
here, so practical risk is negligible. Tracking: #96. Remove once
deb12u2 reaches the bookworm mirror.
expired_at: 2026-08-19
68 changes: 53 additions & 15 deletions images/ci-tools/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,45 @@
# ci-tools — shared linting image for Knight Owl CI pipelines

# ---------- lua builder ----------
# Compiles the Lua 5.4 rocks in a throwaway stage. luarocks, gcc, and the
# liblua5.4-dev → libc6-dev → linux-libc-dev header chain live only here and are
# never copied forward, so the final image ships none of their CVEs.
#
# The base digest is repeated verbatim in the final stage rather than hoisted
# into an ARG: Dependabot's Docker parser only bumps digests written directly in
# FROM, and an `ARG BASE_IMAGE` reference would silence its base-image updates.
# The two FROM lines must stay identical — the native .so modules built here
# load under the final stage's interpreter and need the same glibc ABI.
FROM node:26-bookworm-slim@sha256:b16ca7b4dcfb20184e1c70f9ee30c6a75ed1da669cfafd6d2add4761b123d79f AS lua-builder

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# DL3008: apt packages are intentionally unpinned
# hadolint ignore=DL3008
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
lua5.4 \
liblua5.4-dev \
luarocks \
gcc \
make \
unzip \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*

# ---------- luacheck (Lua 5.4) ----------
ARG LUACHECK_VERSION
RUN luarocks --lua-version=5.4 install luacheck "${LUACHECK_VERSION}" \
&& rm -rf /root/.cache/luarocks

# ---------- busted (Lua 5.4; pulls luassert, say, mediator, term, system) ----------
ARG BUSTED_VERSION
RUN luarocks --lua-version=5.4 install busted "${BUSTED_VERSION}" \
&& rm -rf /root/.cache/luarocks

# ---------- final image ----------
# Base digest duplicated from lua-builder for Dependabot — see the note there.
FROM node:26-bookworm-slim@sha256:b16ca7b4dcfb20184e1c70f9ee30c6a75ed1da669cfafd6d2add4761b123d79f

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
Expand All @@ -17,8 +58,7 @@ RUN apt-get update \
make \
curl \
ca-certificates \
luarocks \
gcc \
lua5.4 \
rsync \
git \
gnupg \
Expand Down Expand Up @@ -111,19 +151,17 @@ ARG STYLELINT_VERSION
RUN npm install -g "stylelint@${STYLELINT_VERSION}" \
&& npm cache clean --force

# ---------- luacheck ----------
ARG LUACHECK_VERSION
RUN luarocks install luacheck "${LUACHECK_VERSION}" \
&& rm -rf /root/.cache/luarocks

# ---------- busted ----------
ARG BUSTED_VERSION
# gcc is purged here because busted is the last luarocks tool that needs
# compilation. If another luarocks tool is added after this, move the purge.
RUN luarocks install busted "${BUSTED_VERSION}" \
&& rm -rf /root/.cache/luarocks \
&& apt-get purge -y --auto-remove gcc \
&& rm -rf /var/lib/apt/lists/*
# ---------- lua toolchain (luacheck + busted on Lua 5.4) ----------
# Rocks are compiled against Lua 5.4 in the builder and copied as artifacts, so
# this image carries no -dev headers, no gcc, and no luarocks. The generated
# wrappers hardcode /usr/bin/lua5.4 and these absolute rock paths, so the copy
# targets must match the builder exactly. luassert (and busted's other deps)
# live under the copied rocks/share/lib trees.
COPY --from=lua-builder /usr/local/lib/luarocks/rocks-5.4 /usr/local/lib/luarocks/rocks-5.4
COPY --from=lua-builder /usr/local/share/lua/5.4 /usr/local/share/lua/5.4
COPY --from=lua-builder /usr/local/lib/lua/5.4 /usr/local/lib/lua/5.4
COPY --from=lua-builder /usr/local/bin/luacheck /usr/local/bin/luacheck
COPY --from=lua-builder /usr/local/bin/busted /usr/local/bin/busted

# ---------- bats-core ----------
ARG BATS_VERSION
Expand Down
4 changes: 3 additions & 1 deletion images/ci-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ CI pipelines. Published to GHCR at `ghcr.io/knight-owl-dev/ci-tools`.
| --- | --- |
| [actionlint](https://github.com/rhysd/actionlint) | GitHub Actions workflow linting |
| [bats](https://github.com/bats-core/bats-core) | Shell script test framework with bats-support, bats-assert, bats-file helper libraries |
| [busted](https://github.com/lunarmodules/busted) | Lua testing framework |
| [busted](https://github.com/lunarmodules/busted) | Lua testing framework (runs on Lua 5.4 to match Pandoc's embedded runtime) |
| [biome](https://github.com/biomejs/biome) | JavaScript/TypeScript linting |
| [chktex](https://www.nongnu.org/chktex/) | LaTeX document linting |
| [git](https://git-scm.com) | Version control (build-time cloning and runtime use) |
| [gpg](https://gnupg.org) | GPG signature verification |
| [hadolint](https://github.com/hadolint/hadolint) | Dockerfile linting |
| [lua](https://www.lua.org) | Lua 5.4 interpreter (runtime for busted; matches Pandoc's HsLua) |
| [luacheck](https://github.com/lunarmodules/luacheck) | Lua script linting |
| [luassert](https://github.com/lunarmodules/luassert) | Lua assertion library (busted dependency) |
| [make](https://www.gnu.org/software/make/) | Build automation |
| [parallel](https://www.gnu.org/software/parallel/) | Parallel execution backend for bats --jobs |
| [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) | Markdown linting |
Expand Down
4 changes: 2 additions & 2 deletions images/ci-tools/versions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ HADOLINT_SHA256_ARM64=331f1d3511b84a4f1e3d18d52fec284723e4019552f4f47b19322a53ce
YQ_VERSION=v4.53.3
YQ_SHA256_AMD64=fa52a4e758c63d38299163fbdd1edfb4c4963247918bf9c1c5d31d84789eded4
YQ_SHA256_ARM64=578648e463a11c1b6db6010cbf41eafed6bee79466fcffa1bb446672cf7945ea
MARKDOWNLINT_CLI2_VERSION=0.22.1
BIOME_VERSION=2.5.1
MARKDOWNLINT_CLI2_VERSION=0.23.0
BIOME_VERSION=2.5.2
STYLELINT_VERSION=17.14.0
LUACHECK_VERSION=1.2.0-1
BUSTED_VERSION=2.3.0-1
Expand Down
4 changes: 4 additions & 0 deletions scripts/ci-tools/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ check "hadolint" "${HADOLINT_VERSION}" hadolint --version
check "yq" "${YQ_VERSION}" yq --version
check "markdownlint-cli2" "${MARKDOWNLINT_CLI2_VERSION}" markdownlint-cli2 --version
check "biome" "${BIOME_VERSION}" biome --version
check "lua" "5.4" lua5.4 -v
check "luacheck" "${LUACHECK_VERSION}" luacheck --version
check "busted" "${BUSTED_VERSION}" busted --version
# luassert ships as a busted dependency (no CLI); confirm the 5.4 interpreter
# can load it — this also exercises the copied rock tree.
check "luassert" "" lua5.4 -e "require('luassert')"
check "chktex" "" chktex --version
check "mandoc" "" command -v mandoc
check "stylelint" "${STYLELINT_VERSION}" stylelint --version
Expand Down