Skip to content

Security: Bump dependencies and remove gnupg2 from runtime - #2130

Merged
moshemorad merged 4 commits into
masterfrom
claude/holmes-cve-scan-patch-sq0uc0
Jul 27, 2026
Merged

Security: Bump dependencies and remove gnupg2 from runtime#2130
moshemorad merged 4 commits into
masterfrom
claude/holmes-cve-scan-patch-sq0uc0

Conversation

@moshemorad

Copy link
Copy Markdown
Contributor

Summary

This PR addresses multiple security vulnerabilities by bumping dependency versions and removes unnecessary packages from the Docker runtime image to reduce the attack surface.

Key Changes

Dependency Updates (pyproject.toml):

Docker Runtime Image Optimization (Dockerfile):

  • Replaced ssh metapackage with openssh-client only (removes unused openssh-server and openssh-sftp-server that carry unfixed CVEs including CVE-2026-60002)
  • Removed gnupg2 from runtime dependencies by using ASCII-armored key format directly with apt (avoids gnupg/dirmngr/gpgsm package family and CVE-2026-24882)
  • Simplified kubectl key setup to use gpg --dearmor removal and direct ASCII-armored key handling
  • Added --no-install-recommends flag to kubectl installation
  • Cleaned up temporary key file handling

Notable Implementation Details

  • Pillow and click are now explicitly pinned in main dependencies rather than relying on transitive resolution, ensuring consistent security updates
  • The Dockerfile changes maintain functionality while reducing the runtime image's CVE footprint by eliminating packages that are never used in the application
  • The kubectl key setup now leverages modern apt capabilities to avoid the need for gnupg2 in the runtime image

https://claude.ai/code/session_01KKy2VCrJKoDNiNrUvjkt8y

claude added 3 commits July 27, 2026 06:46
Scanned the runner image (trivy 0.72.0, Debian 13 base) and poetry.lock,
then patched everything Critical/High plus Mediums older than 60 days.

Python dependency bumps (pyproject.toml + poetry.lock):
- cryptography 46.0.7 -> 48.0.1   GHSA-537c-gmf6-5ccf (High)
- pyjwt 2.12.1 -> 2.13.0          CVE-2026-48526 (High),
                                  CVE-2026-48522/48523/48525 (Medium)
- pyasn1 0.6.3 -> 0.6.4           CVE-2026-59885, CVE-2026-59886 (High)
- pillow 12.2.0 -> 12.3.0         CVE-2026-54058/54059/54060/55379/55380/
                                  59197/59199/59200/59204/59205 (High) and
                                  CVE-2026-55798/59198/59203 (Medium).
                                  Promoted to a main dependency because it is
                                  pulled into the runtime image transitively
                                  via fpdf2/CairoSVG, so a dev-only pin did
                                  not constrain the shipped version.
- tornado 6.5.5 -> 6.5.7          CVE-2026-49853, CVE-2026-49855 (High),
                                  GHSA-pw6j-qg29-8w7f (Medium)
- python-dotenv 0.18.0 -> 1.2.2   CVE-2026-28684 (Medium, published
                                  2026-04-20, older than 60 days)

Runtime image attack-surface reduction. These OS CVEs have no fixed Debian
package available (`apt-get -s upgrade` reports 0 upgrades), so the only
available remediation is to stop shipping packages we never use:
- install openssh-client instead of the "ssh" metapackage. Only the ssh
  client is used (GIT_SSH_COMMAND when cloning playbook repos over git@);
  the metapackage additionally pulled in openssh-server and
  openssh-sftp-server, which carry unfixed CVE-2026-60002 (Critical) plus
  two Highs each.
- drop gnupg2 by feeding apt the kubectl signing key in its original
  ASCII-armored form via signed-by=...asc instead of running `gpg --dearmor`.
  This removes the gnupg/gpg/gpg-agent/gpgconf/gpgsm/dirmngr/gnupg-l10n
  family and its unfixed CVE-2026-24882 (High).
- install kubectl with --no-install-recommends.

Result on the rebuilt image: 113 findings resolved, 0 new.
  Critical 20 -> 17, High 88 -> 60, Medium 133 -> 104, Low 186 -> 133.
No fixable Critical or High findings remain in the image or in poetry.lock.

Deliberately not patched, per the agreed policy (Medium only when older than
60 days):
- idna 3.11, CVE-2026-45409 (Medium, published 2026-06-05, 52 days)
- setuptools 80.10.2, CVE-2026-59890 (Medium, published 2026-07-08, 19 days)
- Flask 2.3.3, CVE-2026-27205 (Low)

The remaining Critical/High findings in the image are perl (via git), curl/
libcurl, libexpat1, util-linux and ncurses. All are marked "affected" or
"fix_deferred" by Debian with no fixed version published, and all are
required by git/kubectl or the base image.

Verified: image builds, kubectl/git/ssh present, sshd and gpg absent,
cryptography+pyjwt sign/verify roundtrip passes, robusta.runner.main imports.
Test suite unchanged from baseline: 19 failed, 287 passed, 11 skipped,
1 error both before and after (all failures are "no cluster reachable" in
this sandbox).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKy2VCrJKoDNiNrUvjkt8y
Cross-checked poetry.lock against the GitHub Advisory / OSV database with
pip-audit, which is the same source Dependabot alerts come from. It surfaced
three High advisories that trivy's vulnerability DB does not yet carry:

- click 8.3.1 -> 8.4.2      CVE-2026-7246 / GHSA-47fr-3ffg-hgmw (High,
                            CVSS 3.1 score 7.2, published 2026-04-30):
                            command injection via unsanitized filename in
                            click.edit(). click is transitive (flask, typer),
                            so it is pinned in the main dependencies.
- kafka-python 2.3.0 -> 2.3.2  CVE-2026-10142 and CVE-2026-10143 (High,
                            CVSS 4.0 score 8.7, published 2026-06-10):
                            denial of service in the protocol frame-length
                            parser and in the SCRAM iteration-count handling.

Nothing in this repository calls click directly, and kafka-python 2.3.2 is a
patch release, so neither bump changes application behaviour.

After this change pip-audit reports only the advisories intentionally left
open under the agreed policy (Medium only when older than 60 days):
flask 3.1.2 CVE-2026-27205 (Low), idna 3.11 CVE-2026-45409 (Medium, 52 days),
pygments 2.19.2 CVE-2026-4539 (Low).

Verified: image rebuilds, click/kafka/flask import, robusta.runner.main
imports, kubectl v1.35.7 present. Test suite still matches baseline exactly
(19 failed, 287 passed, 11 skipped, 1 error - all "no cluster reachable").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKy2VCrJKoDNiNrUvjkt8y
Reconciling against the actual Dependabot alert list showed this Moderate
advisory is older than the 60-day threshold, so it is in scope after all.

Dependabot alert #121 (idna, poetry.lock) corresponds to
GHSA-65pc-fj4g-8rjx / CVE-2026-45409: specially crafted input to
idna.encode() bypasses the CVE-2024-3651 fix.

The advisory was published to the GitHub Advisory Database on 2026-05-19
(69 days), which is what Dependabot dates the alert from. Trivy reports the
later NVD publication date of 2026-06-05 (52 days), which is why the first
pass classified it as inside the 60-day window and skipped it. GHSA dates
are the correct basis here since the policy is applied to Dependabot alerts.

idna is declared optional but ships in the runtime image transitively via
requests/httpx, so the floor is raised on the existing declaration.
Resolves to 3.18.

Verified: image rebuilds, idna.encode() works, robusta.runner.main imports.
Test suite still matches baseline (19 failed, 287 passed, 11 skipped,
1 error - all "no cluster reachable").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKy2VCrJKoDNiNrUvjkt8y
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

Docker image ready for 785b0b3 (built in 2m 25s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:785b0b3
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:785b0b3 me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:785b0b3
docker push me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:785b0b3

Patch Helm values in one line:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set runner.image=me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:785b0b3

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f2b4ad5-8ef3-4c24-aa21-b7dc94418df5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The Docker runtime image now uses a narrower SSH package set, removes runtime GnuPG, and configures the Kubernetes repository with a keyring. Python dependency constraints and related advisory comments were updated across several packages.

Changes

Security updates

Layer / File(s) Summary
Runtime image package and repository setup
Dockerfile
The runtime installs openssh-client instead of ssh, omits gnupg2, and uses an .asc apt keyring through signed-by for kubectl installation.
Python dependency constraint updates
pyproject.toml
Version requirements and advisory comments were updated for multiple Python dependencies, including idna, kafka-python, cryptography, pyjwt, Pillow, and tornado.
Estimated code review effort: 3 (Moderate) ~20 minutes

Possibly related PRs

Suggested reviewers: roiglinik

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main security-focused dependency bumps and runtime image cleanup.
Description check ✅ Passed The description is directly related to the dependency updates and Docker runtime changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/holmes-cve-scan-patch-sq0uc0

Comment @coderabbitai help to get the list of available commands.

The security bumps had been locked with Poetry 2.3.3, which rewrote the file
in lock format 2.1 and re-resolved unrelated packages, inflating the diff.

Regenerated from the original master lock with Poetry 1.8.5 (the version
that produced it) using `poetry lock --no-update`, so only packages affected
by the changed constraints move. Lock format stays 2.0 and the generator
header stays Poetry 1.8.5.

All security pins unchanged: cryptography 48.0.1, pillow 12.3.0,
pyjwt 2.13.0, pyasn1 0.6.4, tornado 6.5.7, python-dotenv 1.2.2,
click 8.4.2, kafka-python 2.3.2, idna 3.18.

Verified: image rebuilds and rescans identically to the previous lock
(Critical 17, High 60, Medium 103, Low 133; no new findings),
robusta.runner.main imports, test suite matches baseline
(19 failed, 287 passed, 11 skipped, 1 error - all "no cluster reachable").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKy2VCrJKoDNiNrUvjkt8y
Comment thread Dockerfile
@moshemorad
moshemorad merged commit 30d54ee into master Jul 27, 2026
5 checks passed
@moshemorad
moshemorad deleted the claude/holmes-cve-scan-patch-sq0uc0 branch July 27, 2026 11:05
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.

3 participants