Skip to content

chore: remove unused runtime packages (libgcrypt, util-linux family, gzip, cracklib)#196

Open
jmromeroes wants to merge 2 commits into
mainfrom
chore/remove-libgcrypt-runtime
Open

chore: remove unused runtime packages (libgcrypt, util-linux family, gzip, cracklib)#196
jmromeroes wants to merge 2 commits into
mainfrom
chore/remove-libgcrypt-runtime

Conversation

@jmromeroes

@jmromeroes jmromeroes commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Eliminates CVEs from packages that have zero runtime consumers in the image, following Ross's Slack guidance.

Two commits, each independently reviewable:

  1. chore: remove libgcrypt from runtime image — libgcrypt has 0 NEEDED entries across all 951 ELF files in the image (Java uses BouncyCastle FIPS via JSSE, not libgcrypt). Added to the existing microdnf remove list; systemd-libs (removed via rpm -e --nodeps earlier in the same block) was the only reason libgcrypt was pulled in.

  2. chore: remove util-linux family + gzip from runtime image — 10 additional packages that have no runtime consumers:

    • util-linux family (7 packages): util-linux, util-linux-core, libblkid, libmount, libsmartcols, libuuid, libfdisk — all reported against the same CVEs by the scanner even though the vuln is in libblkid.
    • cracklib chain (3 packages): cracklib, cracklib-dicts, gzip — transitively pulled in by pam (which is already removed via rpm -e --nodeps in the current block). Ross rejected the gzip waiver noting gzip could be removed instead.

How commit 2 works

openssh declares an RPM file-dep on /sbin/nologin (owned by util-linux), so a straight microdnf remove refuses. We use rpm -e --nodeps to break that declared dep and substitute /sbin/nologin with a symlink to /bin/falsecoreutils-single (still in the image) provides /bin/false with identical exit behavior, so any /etc/passwd shell entries referencing nologin still resolve.

The 5-step removal ordering in commit 2 is dictated by rpm's own runtime deps — the rpm binary dynamically links against libsqlite3, liblzma, libbz2, libarchive (via librpm.so), and transitively libxml2:

  1. rpm -e --nodeps for the existing pre-microdnf list (unchanged): gawk libfido2 systemd-libs p11-kit p11-kit-trust libtasn1 pam libpwquality expat
  2. microdnf remove for everything the depsolver can cleanly resolve — this step adds cracklib cracklib-dicts gzip; removes libxml2/libarchive/sqlite-libs/xz-libs/bzip2-libs/rpm/rpm-libs from this step so rpm stays alive one step longer
  3. rpm -e --nodeps util-linux util-linux-core libblkid libmount libsmartcols libuuid libfdisk (breaks openssh's declared file-dep on /sbin/nologin)
  4. ln -sf /bin/false /sbin/nologin
  5. rpm -e --nodeps rpm rpm-libs libarchive libxml2 sqlite-libs xz-libs bzip2-libs — rpm has already loaded its libs at process start, so it can remove them from the same transaction

Verification

Static analysis

  • Zero linkers for libblkid, libmount, libsmartcols, libuuid, libfdisk, libsqlite3, liblzma, libbz2, libgcrypt across all ELF files in the built image (verified via readelf -d).
  • Zero references to gzip or gunzip in start.sh or the IQ Server bundle.
  • SQLite query of /var/lib/rpm/rpmdb.sqlite confirms all removed packages are absent from the Name table — the Sonatype scanner reads this DB to build its inventory.

Full end-to-end runtime test (real license, real APIs)

Started the built slim image with the sonatype-lc-only.lic license, then exercised the complete IQ Server stack:

Test Result
License upload via POST /api/v2/product/license HTTP 200
All 6 healthchecks (DB × 4 subchecks, deadlocks, license, connections, shutdown, work-dir) All healthy
Docker healthcheck health=healthy
DB write: create org + application IDs returned
Policy evaluation of log4j-core@2.14.0 8 CVEs found (incl. log4shell), 10 violations
Multi-ecosystem eval (maven + npm + pypi, 3 components) 23 CVEs, 28 violations
Full scan pipeline — 4-component CycloneDX SBOM 172 policy violations (92 critical, 76 severe, 4 moderate)
HTML report generation 200 OK
PDF report generation (Birt + PDFBox — fonts, XML, streaming) 670 KB, 11 pages
Raw report JSON (Jackson serialization) 52 KB, valid
ssh -V + ssh-keygen -t ed25519 Both work
Git+SSH handshake (github.com) SSH connection completes
Git+HTTPS deps intact
Java runtime Java 25 functional

Log analysis

Full log scan surfaced 25 WARN/ERROR lines. All fall into one of these expected categories, none related to package removals:

  • PDFBox "Using fallback font LiberationSans" — UBI-minimal ships without Times/Helvetica/Courier; LiberationSans is the standard fallback (pre-existing behavior).
  • HDS URL not configured — expected in test env.
  • Telemetry submit failed — expected in test env (no internet).
  • Lucene Vector API warning — Java 25 vs Lucene version compatibility notice.
  • RelayRegistrationService startup-order retry — unrelated to package changes.

CVEs eliminated (from open waiver requests)

Package CVEs
libgcrypt 2 CVEs previously waived
util-linux family (×7) CVE-2026-13595 on each subpackage
gzip CVE-2026-41991 (Ross-rejected waiver)

Waiver requests for these CVEs have been withdrawn via API.

Testing done

Built and ran Dockerfile.slim locally via docker build --platform linux/amd64. Same removal pattern applied identically to Dockerfile and Dockerfile.rh.

🤖 Generated with Claude Code

jmromeroes and others added 2 commits July 18, 2026 12:08
Adds libgcrypt to the existing microdnf remove list. Verified via `readelf -d`
across all 951 ELF files in the built image: 0 NEEDED entries for
libgcrypt.so. IQ Server (Java) uses BouncyCastle FIPS via JSSE for all
cryptographic operations, not libgcrypt.

libgcrypt is present only as a transitive install-time dep of systemd-libs,
which is itself already removed via the rpm -e --nodeps step earlier in this
block. Since systemd-libs is gone before microdnf remove runs, libgcrypt has
no remaining declared requirer — microdnf's depsolver removes it cleanly.

Validated on Dockerfile.slim (UBI 9.6 / IQ 1.204.2-01):
- /lib64/libgcrypt* absent after build
- Critical binaries (curl, ssh, git, sed, bash) all load without errors
- IQ Server boots, Dropwizard framework serves APIs
- Basic auth (admin:admin123) accepted
- /rest/user/session returns HTTP 200
- /assets/index.html returns HTTP 200
- git ls-remote https://github.com/octocat/Hello-World.git succeeds
  (returns commit SHA — proves libcurl+OpenSSL+zlib+crypto stack functional)
- ssh git@github.com completes ED25519 host key exchange
  (proves openssh client + OpenSSL crypto stack functional)

Eliminates 2 CVEs from the build-stage scan:
  CVE-2026-41989 (libgcrypt ECDH heap overflow via gcry_pk_decrypt)
  CVE-2026-41990 (libgcrypt Dilithium signing bounds check)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eliminates CVEs by removing packages that have no runtime consumers,
per Ross's feedback rejecting the gzip waiver and suggesting util-linux
via rpm -e --nodeps with a /sbin/nologin symlink stand-in.

Runtime verification:
- Zero binaries in the image link libblkid/libmount/libsmartcols/libuuid/
  libfdisk after removal (verified via readelf -d across all ELF files)
- No runtime reference to gzip/gunzip in start.sh or the IQ Server bundle
- ssh, ssh-keygen, git-over-https, and git-over-ssh all continue to work
  despite openssh's declared RPM file-dep on /sbin/nologin (a symlink to
  /bin/false substitutes with identical exit behavior)
- Server boots and admin auth API responds correctly

Ordering: microdnf remove runs first for the packages it can cleanly
resolve, then rpm -e --nodeps removes the util-linux family (breaking
openssh's file-dep), then a final rpm -e removes rpm/rpm-libs plus
libarchive/libxml2/sqlite-libs/xz-libs/bzip2-libs which rpm itself
depends on until it exits.
@rpokorny

Copy link
Copy Markdown
Contributor

@jmromeroes I also believe we can remove gzip. Can you look into that and do it in this same PR if so?

@jmromeroes jmromeroes changed the title chore: remove libgcrypt from runtime image chore: remove unused runtime packages (libgcrypt, util-linux family, gzip, cracklib) Jul 18, 2026
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.

2 participants