Skip to content

Commit 8948fc8

Browse files
authored
Merge branch 'master' into claude/add-mute-intervals-config-aa1kI
2 parents ed34127 + 79c5495 commit 8948fc8

13 files changed

Lines changed: 446 additions & 190 deletions

File tree

.claude/skills/patch-cves/SKILL.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Patching CVEs in Robusta: Automated Workflow
2+
3+
This skill automates the process of identifying and patching CVE vulnerabilities in the Robusta Docker image and Python dependencies, focusing on critical, high, and medium severity issues.
4+
5+
## Overview
6+
7+
The workflow follows this systematic process:
8+
9+
1. **Vulnerability Scanning** - Identify all CVEs in dependencies and Docker image
10+
2. **Severity Filtering** - Focus on critical, high, and medium severity issues
11+
3. **Root Cause Analysis** - Determine which packages/dependencies introduce vulnerabilities
12+
4. **Upstream Research** - Check if newer releases already include fixes
13+
5. **Patch Implementation** - Apply fixes via dependency upgrades or Dockerfile changes
14+
6. **Validation** - Verify CVE fixes and ensure application functionality
15+
16+
## Step-by-Step Process
17+
18+
### 1. Vulnerability Scanning
19+
20+
Use multiple scanning tools to identify vulnerabilities:
21+
22+
```bash
23+
# Scan Docker image for vulnerabilities
24+
docker build -t robusta:latest .
25+
docker scout cves robusta:latest
26+
27+
# Scan Python dependencies for vulnerabilities
28+
pip-audit
29+
safety check
30+
31+
# Validate pyproject.toml metadata and lockfile consistency (does not perform vulnerability scanning)
32+
poetry check
33+
# For CVE scanning of Python dependencies, use pip-audit, safety, or poetry-audit-plugin
34+
```
35+
36+
**What to extract:**
37+
- Affected package name and version
38+
- CVE ID and severity level
39+
- Fixed version (if available)
40+
- Affected version range
41+
42+
### 2. Severity Filtering
43+
44+
Process vulnerabilities in this order:
45+
1. **Critical** - Must be fixed before release
46+
2. **High** - Should be fixed before release
47+
3. **Medium** - Fix when safe and non-breaking
48+
49+
Create a prioritized list and document each CVE:
50+
51+
```
52+
CVE-XXXX-XXXXX (Critical): Package X - affects >=1.0.0,<1.2.0
53+
Fixed in: 1.2.5
54+
Status: Needs patching
55+
56+
CVE-YYYY-YYYYY (High): Package Y - affects >=2.0.0,<2.1.0
57+
Fixed in: 2.1.3
58+
Status: Needs patching
59+
```
60+
61+
### 3. Python Dependency Patches
62+
63+
Two main strategies:
64+
65+
**Strategy A: Direct Upgrade (Preferred)**
66+
- Check `poetry.lock` for affected packages
67+
- Update `pyproject.toml` with patched version
68+
- Run `poetry update package-name`
69+
- Verify in `poetry.lock` that lock file has updated to fixed version
70+
71+
**Strategy B: Transitive Dependency Fix**
72+
- Identify the parent package bringing in vulnerable version
73+
- Upgrade parent package to one with updated dependencies
74+
- This automatically pulls in the fixed transitive dependency
75+
76+
77+
### 4. Dockerfile Patches
78+
79+
For system-level vulnerabilities (non-Python packages):
80+
81+
**Strategy A: Upgrade Base Image**
82+
- Check if newer Python 3.11-slim image includes fixes
83+
- Update FROM statement: `FROM python:3.11-slim` → newer version
84+
85+
**Strategy B: Explicit Package Installation**
86+
- Add specific package upgrade in RUN commands
87+
- Example: `apt-get install -y libssl3` for OpenSSL CVEs
88+
89+
**Strategy C: Apply Patches**
90+
- Use patching tools for targeted fixes in builder stage
91+
- Document with comments explaining which CVEs are fixed
92+
93+
### 5. Validation Checklist
94+
95+
**CVE Verification**
96+
- Run `docker scout cves` again on patched image
97+
- Confirm target CVE no longer appears
98+
- Note any remaining high/critical issues for tracking
99+
100+
**Build Verification**
101+
```bash
102+
# Build the Docker image
103+
docker build -t robusta:test .
104+
105+
# Verify build succeeds with no errors
106+
echo "Build successful"
107+
```
108+
109+
**Functional Testing**
110+
```bash
111+
# Run basic smoke tests
112+
pytest tests/ -v
113+
```
114+
115+
**Dependency Check**
116+
```bash
117+
# Verify no new vulnerabilities introduced
118+
docker scout cves robusta:test --no-cache
119+
120+
# Validate pyproject.toml metadata and lockfile consistency
121+
poetry check --lock
122+
```
123+
124+
### 6. Documentation
125+
126+
Update these files with CVE fix details:
127+
128+
**Dockerfile Comments:**
129+
```dockerfile
130+
# Patching CVE-XXXX-XXXXX (Critical): Package X
131+
RUN apt-get install -y package-name
132+
```
133+
134+
## Key Considerations
135+
136+
### Python Package CVEs
137+
- Check if vulnerability is in the installed wheel vs source
138+
- For indirect dependencies, finding the transitive source is critical
139+
- Use `poetry why package-name` to understand dependency relationships
140+
- Go version matters for Go-based Python bindings (e.g., Cryptography)
141+
142+
### System Library CVEs
143+
- libexpat1, libssl, libc vulnerabilities are common
144+
- These often have fixes in newer base images
145+
- When possible, upgrade the base Python image before manual fixes
146+
147+
### Testing Strategy
148+
- Always rebuild and scan after each patch
149+
- One CVE at a time is safer; group similar fixes together
150+
- Document any CVEs that can't be patched with reasoning
151+
152+
### Breaking Changes
153+
- Verify patched versions don't introduce breaking changes
154+
- Check release notes and migration guides
155+
- Run full test suite, not just smoke tests for major upgrades
156+
157+
## Implementation Notes
158+
159+
1. Work through CVEs in severity order (Critical → High → Medium)
160+
2. For each CVE, follow the complete cycle: identify → research → patch → validate
161+
3. Commit each logical group of fixes separately
162+
4. Keep diagnostics available: `docker scout cves` output, dependency trees, test results
163+
5. If a patch can't be safely applied, document why in the code comments
164+
165+
## Common Issues and Solutions
166+
167+
### Issue: Patch introduces breaking changes
168+
**Solution:**
169+
1. Check if breaking change is in major version bump
170+
2. Review if dependency needs to be pinned differently
171+
3. Consider if a workaround exists (e.g., compatibility shim)
172+
173+
### Issue: Transitive dependency is vulnerable
174+
**Solution:**
175+
1. Find which package brings it in: `poetry why vulnerable-package`
176+
2. Update the parent package instead
177+
3. Re-lock dependencies and verify fix
178+
179+
### Issue: CVE disappears after unrelated patch
180+
**Solution:**
181+
1. Good sign - often due to transitive dependency updates
182+
2. Still verify with `docker scout cves` on final image
183+
3. Update documentation to credit upstream fixes

Dockerfile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ RUN apt-get update \
1111
RUN mkdir /app
1212
WORKDIR /app
1313

14-
RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key -o /app/Release.key
14+
RUN curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key -o /app/Release.key
1515

1616
ENV ENV_TYPE=DEV
1717

@@ -41,6 +41,9 @@ RUN poetry install --without dev --extras "all"
4141
COPY playbooks/ /etc/robusta/playbooks/defaults
4242
RUN pip install --no-cache-dir /etc/robusta/playbooks/defaults
4343

44+
# Patching CVE-2026-24049 (High): wheel path traversal vulnerability
45+
RUN pip install --no-cache-dir "wheel>=0.46.2"
46+
4447
# Fixes k8s library bug - see https://github.com/kubernetes-client/python/issues/1867#issuecomment-1353813412
4548
RUN find /app/venv/lib/python*/site-packages/kubernetes/client/rest.py -type f -exec sed -i 's:^\(.*logger.*\)$:#\1:' {} \;
4649

@@ -66,11 +69,12 @@ WORKDIR /app
6669

6770
# Install necessary packages for the runtime environment
6871
# We're installing here libexpat1, to upgrade the package to include a fix to 3 high CVEs. CVE-2024-45491,CVE-2024-45490,CVE-2024-45492
72+
# Patching glibc for CVE-2026-0861, CVE-2026-0915, CVE-2025-15281
6973
RUN apt-get update \
7074
&& dpkg --add-architecture arm64 \
7175
&& pip3 install --no-cache-dir --upgrade pip \
7276
&& apt-get install -y --no-install-recommends git ssh curl libcairo2 apt-transport-https gnupg2 \
73-
&& apt-get install -y --no-install-recommends libexpat1 \
77+
&& apt-get install -y --no-install-recommends libexpat1 libc6 libc-bin \
7478
&& rm -rf /var/lib/apt/lists/*
7579

7680

@@ -81,17 +85,24 @@ RUN git config --global core.symlinks false
8185
RUN rm -rf /usr/local/lib/python3.11/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl
8286
RUN rm -rf /usr/local/lib/python3.11/site-packages/setuptools-65.5.1.dist-info
8387

88+
# Patching CVE-2026-24049 (High): wheel path traversal vulnerability
89+
# Patching CVE-2026-23949 (High): jaraco.context path traversal vulnerability (vendored in setuptools)
90+
RUN pip3 install --no-cache-dir "wheel>=0.46.2" "setuptools>=80.10.1" \
91+
&& rm -rf /usr/local/lib/python3.11/site-packages/setuptools/_vendor/wheel-0.45.1.dist-info
92+
8493
COPY --from=builder /app/venv /venv
8594
COPY --from=builder /etc/robusta/playbooks/defaults /etc/robusta/playbooks/defaults
8695
# Copy virtual environment and application files from the build stage
8796
COPY --from=builder /app /app
8897
# remove duplicated /app/venv - already copied to /venv
8998
RUN rm -rf /app/venv
99+
# Remove vendored wheel 0.45.1 from setuptools in venv (CVE-2026-24049)
100+
RUN rm -rf /venv/lib/python3.11/site-packages/setuptools/_vendor/wheel*
90101

91102
# Set up kubectl
92103
COPY --from=builder /app/Release.key /tmp/Release.key
93104
RUN cat /tmp/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg \
94-
&& echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list \
105+
&& echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list \
95106
&& apt-get update \
96107
&& apt-get install -y kubectl \
97108
&& rm -rf /var/lib/apt/lists/* \

helm/robusta/Chart.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ dependencies:
44
version: 72.0.1
55
- name: holmes
66
repository: https://robusta-charts.storage.googleapis.com
7-
version: 0.20.0
8-
digest: sha256:003685b2477edb5882fb7733eab823b78f06b0034628b4fc2b62fdf510c4e893
9-
generated: "2026-02-23T22:29:28.355211+02:00"
7+
version: 0.22.0
8+
digest: sha256:25904ebd20cdfb516d243978d343beb438abc6436f96dbc70253d5a710580fe7
9+
generated: "2026-03-18T16:02:40.520552+02:00"

helm/robusta/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ dependencies:
1515
condition: enablePrometheusStack
1616
repository: "https://prometheus-community.github.io/helm-charts"
1717
- name: holmes
18-
version: 0.20.0
18+
version: 0.22.0
1919
condition: enableHolmesGPT
2020
repository: "https://robusta-charts.storage.googleapis.com"
-32.3 KB
Binary file not shown.
33 KB
Binary file not shown.

helm/robusta/values.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ automountServiceAccountToken: true
3838

3939
enableHolmesGPT: false
4040

41+
holmes:
42+
sentryDSN: "https://aa95c183188a6ddf134ebfffe85fd108@o4510692373299200.ingest.de.sentry.io/4510707946094672"
43+
4144
# see https://docs.robusta.dev/master/user-guide/configuration.html#global-config and https://docs.robusta.dev/master/configuration/additional-settings.html#global-config
4245
globalConfig:
4346
check_prometheus_flags: true
@@ -627,7 +630,7 @@ image:
627630
# parameters for the robusta forwarder deployment
628631
kubewatch:
629632
image: ~ # image can be used to override image.registry/imageName
630-
imageName: kubewatch:v2.12.0
633+
imageName: kubewatch:v2.13.0
631634
imagePullPolicy: IfNotPresent
632635
revisionHistoryLimit: 10
633636
pprof: True

playbooks/robusta_playbooks/alerts_integration.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class AlertExplanationParams(ActionParams):
189189
:var recommended_resolution: A recommended resolution for the alert
190190
"""
191191

192-
alert_explanation: str
192+
alert_explanation: Optional[str]
193193
recommended_resolution: Optional[str]
194194

195195

@@ -198,12 +198,15 @@ def alert_explanation_enricher(alert: PrometheusKubernetesAlert, params: AlertEx
198198
"""
199199
Enrich the finding an explanation and recommendation of how to resolve the issue
200200
"""
201-
blocks = [MarkdownBlock(f"{Emojis.Explain.value} *Alert Explanation:* {params.alert_explanation}")]
201+
blocks = []
202+
if params.alert_explanation:
203+
blocks.append(MarkdownBlock(f"{Emojis.Explain.value} *Alert Explanation:* {params.alert_explanation}"))
202204
if params.recommended_resolution:
203-
resolution_block = MarkdownBlock(
204-
f"{Emojis.Recommend.value} *Robusta's Recommendation:* {params.recommended_resolution}"
205+
blocks.append(
206+
MarkdownBlock(f"{Emojis.Recommend.value} *Robusta's Recommendation:* {params.recommended_resolution}")
205207
)
206-
blocks.append(resolution_block)
208+
if not blocks:
209+
return
207210
alert.add_enrichment(
208211
blocks,
209212
annotations={SlackAnnotations.UNFURL: False},

0 commit comments

Comments
 (0)