#1684

DEP-91 (1/5): agent-tools: drop kernel-header CVEs and modernize clean train

Openracerxdlwants to merge intofrom

Stack (DEP-91)

Split from #1662 for reviewability, then rescoped: main has since landed #1681 (dependency/toolchain CVEs) and #1693 (hoophq/hoopagent), which superseded two PRs of the original stack.

  • #1683 — Go dependency + toolchain CVE bumps — closed, superseded by #1681

  • #1685 — opt-in hoophq/hoopdev-minimal — closed, superseded by #1693

  • #1684 — 1. agent-tools: drop kernel-header CVEs, modernize clean train ← you are here

  • #1686 — 2. Vulnerability gates for hoopagent + govulncheck

  • #1687 — 3. SBOM + bundled-tool manifest on releases

  • #1688 — 4. Weekly base-OS rebuild of hoopagent

  • #1689 — 5. Image release integrity hardening

Merge in order, bottom-up. Each PR targets the one below it.

The remaining work is what main still lacks: the fat image's kernel-header CVEs, and any vulnerability gate, SBOM, or scheduled OS patching for hoophq/hoopagent.


What

Removes build-only packages from the agent-tools base image (the base of hoophq/hoopdev) and modernizes the clean train.

  • Drops alien, elfutils, libelf-dev, python3-dev — they pulled in linux-libc-dev (kernel headers, ~891 findings) and libc6-dev with no runtime use.
  • Installs groff and python3-pip with --no-install-recommends.
  • Declares xz-utils explicitly (previously transitive via the removed packages).
  • Uses runtime unixodbc instead of -dev headers.
  • Makes KUBECTL/SQLCMD/MONGOSH/MONGODB_TOOLS versions ARG-driven so the legacy and clean trains can diverge.

Why

Kernel headers were the single largest CVE contributor in the fat image and were never needed at runtime — every bundled CLI is prebuilt.

hoophq/hoopagent (#1693) does not help here: hoophq/hoopdev is a separate image that many deployments still need for exec-based connections and RDP, and main still installs all four packages.

Risk

Legacy-train pins are unchanged, so hoophq/hoopdev keeps its current tool versions. The workflow asserts train contents (legacy keeps the legacy mongo shell; clean ships only mongosh).

How to test

docker build -f Dockerfile.tools -t agent-tools-test .
docker run --rm agent-tools-test sh -c 'dpkg -l | grep -c linux-libc-dev || echo "0 (expected)"'
docker run --rm agent-tools-test sh -c 'psql --version && mongosh --version && kubectl version --client && aws --version'

Expected: no linux-libc-dev; every bundled client still works.

Part of DEP-91.

Automated by MisterMal

Activity

11
qodo-code-review[bot]2mo ago

PR Summary by Qodo

agent-tools: remove kernel-header deps and centralize clean-train versions

✨ Enhancement ⚙️ Configuration changes 🕐 40+ Minutes

AI Description

• Remove build-only packages pulling kernel headers to cut CVE noise in agent-tools.
• Make clean-train tool versions workflow-driven while keeping legacy pins unchanged.
• Build both arches on PRs (no push) to catch arm64-only mismatches pre-merge.
Diagram

graph TD
  WF["agent-tools-build.yml"] --> ARGS["Clean train args"] --> BLD["Buildx (amd64/arm64)"] --> IMG["agent-tools images"] --> GATE["License+provenance gates"] -->|"push (publish only)"| HUB{{"Docker Hub"}}
  DF["Dockerfile.tools"] --> BLD
High-Level Assessment

The following are alternative approaches to this PR:

1. Move clean-train version pins to a repo file (e.g., versions.env)
  • ➕ Single source of truth usable by CI and local builds without copying build-args
  • ➕ Easier for Renovate/custom tooling to bump versions via file-based updates
  • ➖ Adds another config artifact to keep in sync with Dockerfile ARG names
  • ➖ Requires small workflow refactor to read/parse the file reliably
2. Adopt docker-bake with named targets for legacy/clean
  • ➕ More explicit train separation and reusable build definitions (local + CI)
  • ➕ Cleaner multi-arch matrix handling and build-arg reuse
  • ➖ Higher conceptual overhead for contributors unfamiliar with bake
  • ➖ May require broader changes across existing Docker build workflows

Recommendation: The PR’s approach is solid for DEP-91: it keeps legacy pins stable in the Dockerfile while letting clean-train versions move quickly via workflow build-args, and it removes kernel-header sources at the root. If version bumps become frequent, consider extracting clean-train pins into a dedicated versions file to reduce workflow churn and improve local reproducibility.

Files changed (2) +64 / -40

Other (2) +64 / -40
agent-tools-build.ymlCentralize clean-train build args and smoke-build arm64 on PRs +26/-12

Centralize clean-train build args and smoke-build arm64 on PRs

• Adds a workflow output containing all clean-train tool version build-args (and disables legacy mongo for clean). Removes per-job include_legacy_mongo plumbing and makes arm64 builds run on PRs as no-push smoke tests, gating login/push steps on publish runs.

.github/workflows/agent-tools-build.yml

Dockerfile.toolsDrop kernel-header-inducing packages and make key tool pins ARG-driven +38/-28

Drop kernel-header-inducing packages and make key tool pins ARG-driven

• Removes build-only packages (python3-dev/alien/elfutils/libelf-dev) that pulled linux-libc-dev, and installs groff + python3-pip with --no-install-recommends while declaring xz-utils explicitly. Converts kubectl/sqlcmd/mongosh/mongodb-tools versions to ARGs and swaps unixodbc-dev for runtime unixodbc; also confines focal-security/libssl1.1 setup to the legacy-mongo guard.

Dockerfile.tools

qodo-code-review[bot]2mo ago

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


1. Headers removed break derived builds ✓ Resolved 🔗 Cross-repo conflict ☼ Reliability
Description
This PR drops build headers (python3-dev, unixodbc-dev) from hoophq/agent-tools, which is the base
image for hoophq/hoopdev; hoophq/infra’s hoopdev-dck Dockerfile installs native Python deps (e.g.,
pyodbc, pymssql) and may fail to build when infra upgrades its pinned hoopdev tag if any dependency
falls back to an sdist build (especially on non-amd64). Coordinate with infra to add explicit build
deps there or guarantee wheels-only installs.
Code

Dockerfile.tools[R167-169]

+    # DEP-91: runtime unixodbc (libodbc2 + isql), not the -dev headers which
+    # pull linux-libc-dev. Same source version; ODBC runtime preserved.
+    unixodbc=2.3.12-1ubuntu0.24.04.1 \
Relevance

●● Moderate

Cross-repo downstream build-risk; plausible but outside this PR’s scope. Team may note/coordinate,
not revert.

PR-#1595 PR-#1629

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR repo shows hoopdev is built FROM agent-tools and that agent-tools no longer includes python3-dev
and unixodbc-dev; infra repo shows a derived image that pip-installs native-extension packages which
may require those headers if wheels aren’t available.

Dockerfile.dev[1-7] Dockerfile.tools[26-64] Dockerfile.tools[163-176] External repo: hoophq/infra, dock/Dockerfile [1-55]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`hoophq/infra` builds `hoophq/hoopdev-dck` FROM `hoophq/hoopdev`, and `hoophq/hoopdev` is built FROM `hoophq/agent-tools`. This PR removes `python3-dev` and switches from `unixodbc-dev` to `unixodbc` in `agent-tools` (intentionally, to drop kernel headers CVEs). If infra’s `pip3.12 install ... pyodbc/pymssql/...` ever falls back to source builds (wheel gaps, platform differences), the build can fail due to missing Python/ODBC headers.

### Issue Context
- The infra Docker build currently pins `FROM hoophq/hoopdev:1.54.0`; it won’t break immediately, but it can break on the next bump to a hoopdev version built on the new `agent-tools` base.
- This is most likely to surface on architectures where wheels are missing or if dependency versions change.

### Fix Focus Areas
- Dockerfile.tools[26-64]
- Dockerfile.tools[163-176]
- Dockerfile.dev[1-7]
- /cross_repos/infra/dock/Dockerfile[1-55]

### Suggested remediation options
1) In **hoophq/infra** `dock/Dockerfile`, add explicit build deps for the pip layer (only if needed): `python3-dev`, `build-essential`, and `unixodbc-dev` (or pin/ensure wheel-only installs).
2) Alternatively, keep `agent-tools` slim but document this as a breaking contract for downstream images and add a CI build of infra’s Dockerfile against a hoopdev tag built from the new base (coordination/test gate).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Context
✅ Compliance rules (platform): 39 rules
✅ Cross-repo context
  Explored: repo: hoophq/infra (sha: 801e2c0a)
  Not relevant to this PR: hoophq/libhoop
  Not relevant to this PR: hoophq/documentation
  Not relevant to this PR: hoophq/changelog
Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

qodo-code-review[bot]reviewed2mo ago
github-actions[bot]2mo ago

Migration Safety Analysis

No database migrations were changed in this PR. Safe to deploy to sandbox.

github-actions[bot]2mo ago

Migration Safety Analysis

:warning: Automated analysis unavailable -- the LLM API call failed. Please review these migration files manually:

gateway/migrations/000107_access_request_rules_skip_review_groups.down.sql
gateway/migrations/000107_access_request_rules_skip_review_groups.up.sql

Check for:

  • Destructive operations (DROP TABLE, DROP COLUMN, TRUNCATE)
  • Missing or noop .down.sql files
  • Rollback safety for sandbox deployments

Automated analysis by Migration Safety Check.

github-actions[bot]2mo ago

📋 API Changelog

API Changelog unknown vs. unknown

API Changes

GET /access-requests/rules

  • :warning: added the new jit_command enum value to the data/items/access_type response property for the response status 200
  • added the optional property data/items/skip_review_groups to the response with the 200 status

POST /access-requests/rules

  • :warning: added the new jit_command enum value to the access_type response property for the response status 201
  • added the new optional request property skip_review_groups
  • added the new jit_command enum value to the request property access_type
  • added the optional property skip_review_groups to the response with the 201 status

GET /access-requests/rules/{name}

  • :warning: added the new jit_command enum value to the access_type response property for the response status 200
  • added the optional property skip_review_groups to the response with the 200 status

PUT /access-requests/rules/{name}

  • :warning: added the new jit_command enum value to the access_type response property for the response status 200
  • added the new optional request property skip_review_groups
  • added the new jit_command enum value to the request property access_type
  • added the optional property skip_review_groups to the response with the 200 status

GET /connection-credentials

  • endpoint added
sandromello2mo ago

✅ Build Completed with Success, Version=1684.0.0-g48d32b1

sandromello2mo ago

✅ Build Completed with Success, Version=1684.0.0-g48d32b1

sandromello2mo ago

✅ Build Completed with Success, Version=1684.0.0-g0473ea4