Skip to content

Commit 79c5495

Browse files
authored
Patch cves (#2035)
1 parent 14d6ba5 commit 79c5495

4 files changed

Lines changed: 226 additions & 27 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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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,12 +85,19 @@ 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

poetry.lock

Lines changed: 25 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ supabase = "2.5.1"
2828
tabulate = { version = "^0.8.10" }
2929
slack-sdk = { version = "^3.23.0" }
3030
Flask = { version = "^3.0.0", optional = true }
31-
werkzeug = { version = ">=3.0.6", optional = true }
31+
werkzeug = { version = ">=3.1.6", optional = true }
3232
jinja2 = { version = ">=3.1.5", optional = true }
3333
grafana-api = { version = "^1.0.3", optional = true }
3434
watchdog = { version = "^2.1.0", optional = true }
@@ -71,12 +71,14 @@ prometheus-api-client = "0.5.4"
7171
requests = "^2.32.3"
7272
certifi = "^2023.7.22"
7373
regex = "2024.5.15"
74-
pyjwt = "^2.4.0"
75-
urllib3 = "^2.6.2"
74+
pyjwt = "^2.12.0"
75+
urllib3 = "^2.6.3"
7676
httpx = "0.27.2"
7777
postgrest = "0.16.8"
7878
# Pin to fix cve https://github.com/robusta-dev/robusta/security/dependabot/85
79-
h2 = "^4.3.0"
79+
h2 = "^4.3.0"
80+
# Pin to fix CVE-2026-30922 (transitive via google-auth)
81+
pyasn1 = ">=0.6.3"
8082

8183
[tool.poetry.dev-dependencies]
8284
pre-commit = "^2.13.0"

0 commit comments

Comments
 (0)