Skip to content

fix(image): drop unused binaries, bump bundled tools, scan the image with Trivy - #118

Merged
agentHits merged 3 commits into
AgentHits-Devfrom
fix/image-vulnerabilities
Oct 28, 2026
Merged

agentHits merged 3 commits into
AgentHits-Devfrom
fix/image-vulnerabilities

Conversation

@agentHits

@agentHits agentHits commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

bun audit проверяет только npm-зависимости. Пакеты Debian и бинарники инструментов в образе панели он не видит. Trivy 0.76.1 нашёл в образе agenthits-v1.0.8 2 critical и 211 high. Исправление уже вышло для 89 high, и все они не в Debian:

  • Go stdlib и golang.org/x/* в Docker CLI, движке Docker, rclone, Railpack и pack.
  • undici и brace-expansion в npm, который встроен в образ Node.
  • Компилятор TypeScript 7 (Go-бинарник) в рабочем node_modules.

Этот PR убирает лишнее, обновляет инструменты и добавляет проверку образа в CI.

Что изменилось в образе

  • Docker. Ставится только docker-ce-cli 29.9.2 с плагинами buildx и compose из apt-репозитория Docker. Раньше get.docker.com ставил ещё движок, containerd, runc, rootlesskit и плагин docker-model. Панели они не нужны: она работает с Docker хоста через сокет.
  • Инструменты.
    • rclone 1.75.1 → 1.75.2.
    • Railpack 0.40.1 → 0.42.0. Версию 0.43.0 не берём: в ней ломающее изменение исключений в контексте сборки, а уязвимости закрыты те же.
    • pack 0.40.9 → 0.40.10.
  • TypeScript. Компилятор удалён из рабочего node_modules: его притягивают пакеты @trpc/* как обязательную peer-зависимость, а во время работы он не нужен.
  • npm, npx и node-gyp удалены из финального образа: панель запускается через node и bun.
  • Системные пакеты ставятся без «рекомендуемых». Ушли systemd, dbus, iptables, apparmor и библиотеки X11. Нужные панели openssh-client, procps (им отменяется деплой), xz-utils и netbase перечислены явно.

Версии компонентов на серверах

Версии синхронизированы во всех местах, которые сверяет component-versions-sync.test.ts: Docker Engine для серверов теперь 29.9.2, rclone 1.75.2, Railpack 0.42.0, pack 0.40.10. Кнопка Components → Update на карточке сервера предложит эти версии. Обновление Docker перезапускает демон и сервисы swarm на этом сервере.

Новые приложения получают Railpack 0.42.0 по умолчанию (миграция 0210_railpack_default_0_42_0). Существующие приложения сохраняют свою версию фронтенда Railpack.

Проверка образа в CI

  • bun-migration-docker-check.yml после сборки образа в PR вызывает все инструменты, которые запускает панель, и сканирует образ Trivy.
  • Там же собирается тестовое Node-приложение тем же путём, что в панели: railpack prepare из образа, затем docker buildx с фронтендом Railpack. Приложение запускается и должно ответить по HTTP. При ручном запуске можно указать другой фронтенд (railpack-frontend), например версию, которую сохраняют существующие приложения.
  • Новый image-audit.yml каждый понедельник сканирует опубликованный agenthits-dev. Новые уязвимости появляются и без изменений в коде.
  • Обе проверки падают на critical и high, у которых есть исправление. Находки Debian без исправления не учитываются: Debian 12 их пока не исправил, а Debian 13 почти ничего не меняет.
  • Trivy закреплён по digest, а не по тегу. В марте 2026 релизы Trivy и теги trivy-action подменяли (GHSA-69fq-xp46-6x23).
  • .trivyignore.yaml содержит три уязвимости, которые остаются даже в последних релизах buildx, compose, rclone и Railpack. Каждая запись действует до 2026-11-27. После этого проверка снова упадёт и напомнит проверить новые релизы.

Что осталось

  • В пакетах Debian 12 остаются 2 critical и около 106 high без исправлений. Самая заметная — openssh-client CVE-2026-60002. Вторая critical, в zlib1g (CVE-2023-45853), касается кода minizip, которого в пакете нет.
  • После PR ожидается 5 исправимых high, все в .trivyignore.yaml: buildx и compose (golang.org/x/net, moby/go-archive), rclone и Railpack (Go stdlib, нужен Go 1.26.10).

Проверки

  • Скан agenthits-v1.0.8: 2 critical, 211 high, из них 89 исправимых.
  • CI этого PR собрал полный образ под amd64:
    • в нём Docker 29.9.2, buildx 0.38.1, compose 5.6.1, rclone 1.75.2, Railpack 0.42.0, pack 0.40.10 и nixpacks 1.41.0;
    • все утилиты, которые вызывает панель, на месте;
    • dockerd, containerd, npm и компилятора TypeScript в образе нет;
    • Trivy не нашёл исправимых critical и high ни в одном компоненте.
  • Сборка через Railpack:
    • тестовое Node-приложение собрано с фронтендом 0.42.0 (новые приложения) и, отдельным ручным запуском, с фронтендом 0.40.1 (существующие приложения, план от бинарника 0.42.0);
    • оба образа запустились и ответили по HTTP.
  • Миграция 0210 на Postgres 18.6:
    • база доведена до 0209, в неё добавлены два приложения с версиями 0.40.1 и 0.15.4, затем применены миграции из ветки;
    • значение по умолчанию стало 0.42.0, версии существующих приложений не изменились, новое приложение получило 0.42.0;
    • повторный запуск ничего не меняет.
  • Панель из образа agenthits-dev, где TypeScript и npm скрыты, запущена с Postgres и Redis: миграции прошли, health 200, /register 200. Кода, который загружает typescript во время работы, в образе нет.
  • server-components.test.ts теперь берёт версию Docker из PINNED_VERSIONS.docker: 18 тестов держали 29.8.2 строкой. Тесты: 4278 прошли, 1 пропущен.
  • Biome, bash -n и actionlint без замечаний.
  • Не проверено: обновление компонентов кнопкой Components → Update на живом сервере.

🤖 Generated with Claude Code

…with Trivy

Что:
- Образ панели ставит из apt-репозитория Docker только docker-ce-cli 29.9.2 с плагинами buildx и compose. Движок, containerd, runc, rootlesskit и docker-model, которые добавлял get.docker.com, убраны: панель работает с Docker хоста через сокет.
- rclone 1.75.1 → 1.75.2, Railpack 0.40.1 → 0.42.0, pack 0.40.9 → 0.40.10. Docker Engine для серверов закреплён на 29.9.2. Версии поменяны во всех местах, которые сверяет component-versions-sync.test.ts: component-versions.ts, install-agenthits.sh, update.sh, Dockerfile, pull-request.yml, выбор Railpack в форме приложения. Таблица в docs/server-components-update.md обновлена.
- Railpack 0.43.0 не взят: в нём ломающее изменение исключений в контексте сборки, а уязвимости закрыты те же, что в 0.42.0.
- Миграция 0210: новые приложения получают railpackVersion 0.42.0 по умолчанию. Существующие приложения сохраняют свою версию.
- Из рабочего node_modules удалён компилятор TypeScript 7 (Go-бинарник, 27 МБ). Его притягивают пакеты @trpc/* как обязательную peer-зависимость, а во время работы он не используется.
- Из финального образа удалены npm, npx и node-gyp: панель запускается через node и bun.
- Системные пакеты финальной стадии ставятся с --no-install-recommends. Нужные панели openssh-client, procps, xz-utils и netbase перечислены явно. Ушли systemd, dbus, iptables, apparmor и библиотеки X11.
- Trivy 0.76.1, закреплённый по digest, сканирует образ, который собирает PR (bun-migration-docker-check.yml), и опубликованный agenthits-dev каждый понедельник (новый image-audit.yml). Проверка падает на critical и high, у которых есть исправление.
- В .trivyignore.yaml три находки, которые есть даже в последних релизах buildx, compose, rclone и Railpack. У каждой срок до 2026-11-27.
- Smoke-проверка образа в PR теперь вызывает все инструменты, которые панель запускает.
- В CLAUDE.md описан аудит образа.

Зачем:
- bun audit видит только npm-зависимости. В образе agenthits-v1.0.8 Trivy нашёл 2 critical и 211 high, из них 89 high с исправлением: Go stdlib и golang.org/x/* в инструментах, undici и brace-expansion во встроенном npm, компилятор TypeScript.
- В пробной сборке ОС с инструментами исправимых high стало 3 вместо 75. На весь образ ожидается 5, и все пять ждут релиза своего инструмента.
- Находки в пакетах Debian 12 (2 critical, около 106 high) остаются. Debian не выпустил для них исправлений, и Debian 13 почти ничего не меняет, поэтому проверка их не учитывает (--ignore-unfixed).

Риски:
- Railpack 0.41–0.42 меняет поведение сборок: Java по умолчанию на Temurin, проверка подписи Node, кэш Turborepo. Существующие приложения сохраняют свою версию фронтенда, но план сборки строит бинарник 0.42.0 из образа.
- Кнопка Components → Update предложит Docker 29.9.2, rclone 1.75.2, Railpack 0.42.0 и pack 0.40.10 на серверах. Обновление Docker перезапускает демон и сервисы swarm.
- --no-install-recommends может убрать редкую утилиту, которую панель вызывает. Основные утилиты перечислены в smoke-проверке PR.
- Новая уязвимость с исправлением остановит PR, который меняет образ, пока инструмент не обновят или не внесут находку в .trivyignore.yaml.

Проверки:
- Команды и результаты: Trivy 0.76.1 по agenthits-v1.0.8 — 2 C и 211 H, исправимых 89. Пробная сборка ОС с Docker CLI 29.9.2 из apt и без recommends — исправимых high 3. Новые бинарники rclone 1.75.2, Railpack 0.42.0, pack 0.40.10 и docker 29.9.2 — по 0–1 исправимой high. vitest component-versions-sync.test.ts — 26 из 26. biome check по изменённым TS-файлам — без замечаний. bash -n install-agenthits.sh update.sh — ок. actionlint по новым workflow — без замечаний. Панель из образа agenthits-dev со скрытыми TypeScript и npm запущена с Postgres 18.6 и Redis: миграции прошли, health 200, /register 200. Кода, который загружает typescript во время работы, в образе нет.
- Ограничения: полный образ локально не собран: Bun падает под эмуляцией amd64 на arm64, а на диске Docker не хватило места для сборки arm64. Сборку amd64, вызов инструментов и скан выполняет CI этого PR. Миграция 0210 на живой базе не проверена. Сборка приложения через Railpack 0.42.0 не проверена.

What:
- The panel image installs only docker-ce-cli 29.9.2 with the buildx and compose plugins from Docker's apt repository. The engine, containerd, runc, rootlesskit and docker-model that get.docker.com added are gone: the panel drives the host's Docker through the socket.
- rclone 1.75.1 → 1.75.2, Railpack 0.40.1 → 0.42.0, pack 0.40.9 → 0.40.10. Docker Engine for servers is pinned to 29.9.2. Versions changed everywhere component-versions-sync.test.ts compares: component-versions.ts, install-agenthits.sh, update.sh, Dockerfile, pull-request.yml, the Railpack picker of the application form. The table in docs/server-components-update.md is updated.
- Railpack 0.43.0 is skipped: it changes build-context excludes in a breaking way and fixes the same advisories as 0.42.0.
- Migration 0210: new applications default to railpackVersion 0.42.0. Existing applications keep their version.
- The TypeScript 7 compiler (a 27 MB Go binary) is removed from the production node_modules. The @trpc/* packages pull it in as a required peer; nothing loads it at runtime.
- npm, npx and node-gyp are removed from the final image: the panel runs on node and bun.
- The final stage installs system packages with --no-install-recommends. openssh-client, procps, xz-utils and netbase, which the panel needs, are listed explicitly. systemd, dbus, iptables, apparmor and the X11 libraries are gone.
- Trivy 0.76.1, pinned by digest, scans the image a PR builds (bun-migration-docker-check.yml) and the published agenthits-dev every Monday (new image-audit.yml). The check fails on critical and high findings that have a fix.
- .trivyignore.yaml lists three findings that even the latest buildx, compose, rclone and Railpack releases carry. Each entry expires on 2026-11-27.
- The PR image smoke now calls every tool the panel runs.
- CLAUDE.md describes the image audit.

Why:
- bun audit sees only the npm dependencies. In agenthits-v1.0.8 Trivy found 2 critical and 211 high, 89 high with a fix: Go stdlib and golang.org/x/* in the tools, undici and brace-expansion in the bundled npm, the TypeScript compiler.
- A probe build of the OS and tools went from 75 fixable high to 3. For the whole image 5 are expected, all waiting for a release of their tool.
- Findings in Debian 12 packages (2 critical, about 106 high) remain. Debian has no fixes for them and Debian 13 barely differs, so the check leaves them out (--ignore-unfixed).

Risks:
- Railpack 0.41–0.42 changes build behaviour: Java defaults to Temurin, Node downloads are GPG-verified, Turborepo cache. Existing applications keep their frontend version, but the plan comes from the 0.42.0 binary in the image.
- Components → Update will offer Docker 29.9.2, rclone 1.75.2, Railpack 0.42.0 and pack 0.40.10 on servers. A Docker update restarts the daemon and the swarm services.
- --no-install-recommends may drop a rarely used utility the panel calls. The main ones are listed in the PR smoke.
- A new fixable advisory stops a PR that changes the image until the tool is bumped or the finding goes into .trivyignore.yaml.

Checks:
- Commands and results: Trivy 0.76.1 on agenthits-v1.0.8 — 2 C and 211 H, 89 fixable. Probe build of the OS with Docker CLI 29.9.2 from apt and without recommends — 3 fixable high. New rclone 1.75.2, Railpack 0.42.0, pack 0.40.10 and docker 29.9.2 binaries — 0–1 fixable high each. vitest component-versions-sync.test.ts — 26 of 26. biome check on the changed TS files — clean. bash -n install-agenthits.sh update.sh — ok. actionlint on the new workflows — clean. The panel from the agenthits-dev image with TypeScript and npm hidden ran against Postgres 18.6 and Redis: migrations passed, health 200, /register 200. No code in the image loads typescript at runtime.
- Limitations: the full image was not built locally: Bun crashes under amd64 emulation on arm64, and the Docker disk had no room for an arm64 build. The amd64 build, the tool calls and the scan run in this PR's CI. Migration 0210 was not run on a live database. An application build with Railpack 0.42.0 was not tried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentHits and others added 2 commits October 28, 2026 12:42
Что:
- server-components.test.ts берёт версию Docker из PINNED_VERSIONS.docker: в поддельном выводе apt-cache madison, в FAKE_TARGET_ENGINE, в DOCKER_NEW и в двух ожидаемых сообщениях «Docker not updated».
Зачем:
- 18 тестов держали 29.8.2 строкой и упали в pr-check (test) после перехода на 29.9.2. Следующее обновление Docker их больше не сломает.
Риски:
- не выявлены.
Проверки:
- Команды и результаты: vitest server-components.test.ts, install-agenthits-update.test.ts, component-versions-sync.test.ts, railpack.command.test.ts — 177 из 177; biome check — без замечаний.
- Ограничения: полный набор тестов прогонит CI.

What:
- server-components.test.ts takes the Docker version from PINNED_VERSIONS.docker: in the fake apt-cache madison output, in FAKE_TARGET_ENGINE, in DOCKER_NEW and in the two expected "Docker not updated" messages.
Why:
- 18 tests held 29.8.2 as a literal and failed in pr-check (test) after the move to 29.9.2. The next Docker bump will not break them.
Risks:
- none identified.
Checks:
- Commands and results: vitest server-components.test.ts, install-agenthits-update.test.ts, component-versions-sync.test.ts, railpack.command.test.ts — 177 of 177; biome check — clean.
- Limitations: CI runs the full suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Что:
- main-image-smoke изнутри образа панели повторяет путь, которым панель собирает приложения через Railpack: railpack prepare, затем docker buildx с фронтендом Railpack на builder с драйвером docker-container. Собирается минимальное Node-приложение, затем оно запускается и отвечает на HTTP.
- Ручной запуск принимает railpack-frontend: так можно проверить фронтенд, который сохраняют существующие приложения (например 0.40.1), с планом от нового бинарника.
Зачем:
- Обновление Railpack, которое не может собрать простое приложение, теперь ловится в PR, а не после выкатки.
Риски:
- Шаг добавляет около минуты и скачивает образы сборщика Railpack в PR, которые меняют образ.
Проверки:
- Команды и результаты: actionlint — без замечаний. Сам шаг проверяется в CI этого PR.
- Ограничения: локально не запускался: на диске Docker нет места.

What:
- main-image-smoke repeats, from inside the panel image, the path the panel uses to build Railpack applications: railpack prepare, then docker buildx with the Railpack frontend on a docker-container builder. It builds a minimal Node app, then runs it and expects an HTTP answer.
- A manual run takes railpack-frontend, to check a frontend existing applications keep (e.g. 0.40.1) with a plan from the new binary.
Why:
- A Railpack bump that cannot build a plain app now fails in the PR instead of after a rollout.
Risks:
- The step adds about a minute and pulls the Railpack builder images in PRs that change the image.
Checks:
- Commands and results: actionlint — clean. The step itself is checked by this PR's CI.
- Limitations: not run locally: the Docker disk has no room.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@agentHits
agentHits merged commit 0dac295 into AgentHits-Dev Oct 28, 2026
11 checks passed
agentHits added a commit that referenced this pull request Oct 28, 2026
The Drizzle schema default of webServerSettings.whitelabelingConfig has
the keys passwordResetGuide and supportEmail, but the database default
set by the migrations does not. Upstream commit 44fc4cc ("custom
forgot password flow in whitelabeling settings") added the keys to the
schema without a migration, and the upstream sync of 2026-10-26 (#87)
brought that into the fork. Upstream canary has no migration for it
either. Every drizzle-kit generate therefore emitted
ALTER COLUMN "whitelabelingConfig" SET DEFAULT, and any schema change
picked it up as an unrelated statement (#118 had to drop it by hand).

Migration 0211_whitelabeling_config_default, right after #118's
0210_railpack_default_0_42_0, sets the column default to the schema's:
the same object plus "passwordResetGuide":null and "supportEmail":null.
drizzle-kit generate now reports no changes.

Only the default changes, so only rows inserted later (a fresh install)
get the keys. Existing rows are not backfilled: every reader treats a
missing key as null (getPublicWhitelabelingConfig with ?? null, the
login page with !!supportEmail, the settings form with ?? ""), and save
and reset write the whole object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentHits added a commit that referenced this pull request Oct 28, 2026
…ult (#119)

The Drizzle schema default of webServerSettings.whitelabelingConfig has
the keys passwordResetGuide and supportEmail, but the database default
set by the migrations does not. Upstream commit 44fc4cc ("custom
forgot password flow in whitelabeling settings") added the keys to the
schema without a migration, and the upstream sync of 2026-10-26 (#87)
brought that into the fork. Upstream canary has no migration for it
either. Every drizzle-kit generate therefore emitted
ALTER COLUMN "whitelabelingConfig" SET DEFAULT, and any schema change
picked it up as an unrelated statement (#118 had to drop it by hand).

Migration 0211_whitelabeling_config_default, right after #118's
0210_railpack_default_0_42_0, sets the column default to the schema's:
the same object plus "passwordResetGuide":null and "supportEmail":null.
drizzle-kit generate now reports no changes.

Only the default changes, so only rows inserted later (a fresh install)
get the keys. Existing rows are not backfilled: every reader treats a
missing key as null (getPublicWhitelabelingConfig with ?? null, the
login page with !!supportEmail, the settings form with ?? ""), and save
and reset write the whole object.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant