Skip to content

v0.37.0

Choose a tag to compare

@KIvanow KIvanow released this 12 Aug 14:46
· 7 commits to master since this release
bef08ef

v0.37.0

Container hardening release: the Docker image is rebuilt clean and roughly half the size. The migration binary no longer drags an EOL Go runtime's CVEs into your cluster, the base image and bundled tooling are patched or removed, and the image scanner goes from 138 findings (4 critical, 52 high) to 11 (0 critical, 0 high).

No breaking changes; no config or migration steps required.

🔒 Container security

  • RedisShake migration binary rebuilt from source (Go 1.26). The upstream prebuilt release is compiled with Go 1.21.13 — a standard library that went end-of-life two years ago and carries dozens of CVEs, including criticals (CVE-2025-64121, CVE-2025-22871). These are welded into a statically-linked binary, so apk upgrade can't touch them. We now build RedisShake from source (pinned to the v4.6.1 release commit) against a current toolchain, and bump its embedded golang.org/x/text 0.14.0 → 0.39.0 (CVE-2026-56852).
  • Base image node:25-alpinenode:26-alpine. Node 25 is a non-LTS line with no patch for CVE-2026-56848 / CVE-2026-58043; node 26 (LTS) carries the fixes.
  • Removed the npm CLI from the runtime image. The image builds with pnpm; the bundled npm was unused at runtime and only contributed its own vendored-dependency CVEs (tar, brace-expansion, picomatch, sigstore, ip-address).
  • Removed the GNU tar package. It shipped currently-unfixable Alpine CVEs and was redundant — busybox already provides tar.
  • Net result: image scan goes from 138 findings → 11, and 4 critical + 52 high → 0 + 0. The 11 that remain are Medium/Low items with no upstream fix yet (busybox/ssl_client and a couple of suite-locked transitive deps) — left in the open rather than hidden.

📦 Image size — roughly halved

  • A single chown -R /app was duplicating the entire ~600 MB node_modules into a second overlay layer just to change ownership bits. Switched to COPY --chown (ownership set as files are written — one layer, not two), plus COPY --chmod for the migration binary.
    • Default (no-AI) image: 1.34 GB → 744 MB.
    • AI image: 2.22 GB → 1.17 GB.
  • Every pull moves less data, every deploy is faster, every node caches more.

🛠️ Fixes & build

  • Health check corrected. It now probes /api/health (the previous path hit the SPA fallback and reported healthy regardless of API state) using the base image's busybox wget — no extra package, and no interpreter cold-start that could exceed the 3 s timeout under the CPU pressure of a running migration.
  • Restored /app write access for the non-root runtime user. The layer-dedup change had left /app root-owned, which broke features that write there at runtime — notably RedisShake's working directory during a migration, and SQLite/license paths. Fixed non-recursively (no size regression).
  • arm64 image now cross-compiles natively instead of running the Go toolchain under QEMU emulation (--platform=$BUILDPLATFORM) — faster, more reliable multi-arch builds.
  • The shipped redis-shake binary now reports its real version (v4.6.1 + commit) instead of unknown in migration logs.

Thanks to @jamby77 for the thorough review that tightened the build (native cross-compile, busybox health check, version stamping, single-layer binary).