Skip to content

Commit 30aa6e3

Browse files
Document thrift CPE-gap accurately + add weekly NVD-CPE thrift watch
Corrects the earlier "thrift ~=0.22.0 (no known advisory)" wording, which was wrong: thrift 0.22.0 IS affected by open Apache Thrift advisories (CVE-2025-48431 + the CVE-2026-41602..41636 set, all fixed in 0.23.0). Why we still hold at ~=0.22.0 and accept them: - Apache Thrift is one monorepo shipping ~20 language libraries; the PyPI `thrift` package is built only from lib/py. Each of these CVEs is in a NON-Python binding -- verified against the upstream oss-security advisories: Node.js (41636), Go (41602), c_glib/C (48431), Java (41603), Swift (41604, 41605). None touches the Python code paths we ship. - The only fix (0.23.0) is the version that caused SEV0 ES-1960554 on DBR-LTS old setuptools, so we cannot take it until a build-safe thrift ships (THRIFT-6067). Why the OSV gate doesn't flag it (and why that is NOT proof Python is safe): - These CVEs are in OSV with `affected[].package = null` -- only a GIT/CPE coordinate (cpe:2.3:a:apache:thrift), no PyPI/npm/Go package entry. OSV and Dependabot both match by package purl, so they return nothing for PyPI thrift. This is a coordinate blind spot, independent of whether Python is affected -- a FUTURE Python-affecting thrift CVE filed the same way would also be missed. Mitigation: a supplementary NVD-CPE thrift watch in securityScan.yml, scheduled/manual only (never PR; NVD rate limits). It lists all apache:thrift CVEs affecting the locked version in the weekly summary and hard-fails if any description names Python. Scoped to thrift alone because an audit of all three drivers' full dependency sets found thrift is the only dep with this purl-vs-CPE gap (Go/Node already ship the fixed 0.23.0). The Python-detection is a heuristic (description must say python/lib/py); the full list is always surfaced for human review. Co-authored-by: Isaac Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
1 parent 334331a commit 30aa6e3

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

.github/workflows/securityScan.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,88 @@ jobs:
264264
echo "Full step summary: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
265265
exit 1
266266
267+
# --- Supplementary: thrift NVD-CPE watch (scheduled/manual only) ---
268+
# OSV-Scanner (and Dependabot) match by PyPI purl. The Apache Thrift CVEs
269+
# are filed ONLY against the upstream CPE (cpe:2.3:a:apache:thrift) with
270+
# no PyPI-package coordinate, so the purl gate above is structurally BLIND
271+
# to them (see the thrift note in pyproject.toml). We hold thrift at
272+
# ~=0.22.0 on purpose (0.23.0 fixes the CVEs but reintroduces the
273+
# ES-1960554 DBR-LTS install break), and every known thrift CVE to date
274+
# is in a non-Python binding -- so we are not exposed today. But that is a
275+
# point-in-time fact: a FUTURE thrift CVE could land in the Python binding
276+
# and the purl gate would never see it.
277+
#
278+
# This step closes that one blind spot cheaply: query NVD by CPE for
279+
# apache:thrift advisories affecting our locked version, and LOUDLY flag
280+
# any whose description mentions Python (the only case we're exposed to).
281+
# It is scoped to thrift alone (not a general CPE sweep) because thrift is
282+
# the sole dependency in the lock with this purl-vs-CPE gap (audited).
283+
# Runs on the weekly/manual event only -- never on PRs -- because NVD
284+
# rate-limits unauthenticated callers and this is a safety net, not a gate.
285+
#
286+
# HEURISTIC, not a guarantee: the Python-detection relies on the NVD
287+
# description containing "python" / "lib/py" / "PyPI". Apache files these
288+
# per-binding, but some descriptions read only "Apache Thrift" with no
289+
# language named (e.g. CVE-2026-41606). Such a finding is listed in the
290+
# weekly summary (TOTAL count) but would NOT auto-escalate. So: the FULL
291+
# list is always surfaced for human review; only the clearly-Python ones
292+
# hard-fail. Treat the weekly summary as a prompt to eyeball new thrift
293+
# CVEs, not as proof none affect Python.
294+
- name: Thrift NVD-CPE watch (CPE-only advisories the purl gate can't see)
295+
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
296+
run: |
297+
set -uo pipefail
298+
299+
# Locked thrift version from poetry.lock (authoritative shipped version).
300+
THRIFT_VER=$(awk '/^\[\[package\]\]/{n=""} /^name = /{gsub(/"/,"");n=$3} n=="thrift" && /^version = /{gsub(/"/,"");print $3; exit}' poetry.lock)
301+
if [ -z "${THRIFT_VER:-}" ]; then
302+
echo "::warning::Could not determine locked thrift version; skipping NVD-CPE thrift watch."
303+
exit 0
304+
fi
305+
echo "Checking NVD for apache:thrift advisories affecting thrift $THRIFT_VER ..."
306+
307+
# Exact-version CPE match against NVD. Non-fatal on transport errors
308+
# (this is a supplementary watch, not the gate) -- but a Python-
309+
# affecting hit escalates to an error below.
310+
NVD_URL="https://services.nvd.nist.gov/rest/json/cves/2.0?cpeName=cpe:2.3:a:apache:thrift:${THRIFT_VER}:*:*:*:*:*:*:*"
311+
nvd_rc=0
312+
curl -fsSL --max-time 60 "$NVD_URL" -o /tmp/thrift-nvd.json || nvd_rc=$?
313+
if [ "$nvd_rc" -ne 0 ] || [ ! -s /tmp/thrift-nvd.json ]; then
314+
echo "::warning::NVD query failed (rc=$nvd_rc, e.g. rate limit). Thrift CPE watch inconclusive this run."
315+
exit 0
316+
fi
317+
318+
TOTAL=$(jq '.totalResults // 0' /tmp/thrift-nvd.json)
319+
echo "NVD apache:thrift CVEs affecting $THRIFT_VER: $TOTAL"
320+
321+
# Findings whose description mentions Python -> the ONLY class we are
322+
# actually exposed to (all others are non-Python bindings we accept).
323+
PY_HITS=$(jq -r '
324+
[ .vulnerabilities[]?.cve
325+
| select( ([.descriptions[]? | select(.lang=="en") | .value] | join(" ")) | test("python|lib/py|PyPI"; "i") )
326+
| .id ] | unique | join(", ")
327+
' /tmp/thrift-nvd.json)
328+
329+
{
330+
echo "## Thrift NVD-CPE watch"
331+
echo ""
332+
echo "- Locked thrift version: \`$THRIFT_VER\`"
333+
echo "- NVD \`apache:thrift\` CVEs affecting it: \`$TOTAL\` (purl gate cannot see these)"
334+
if [ -n "$PY_HITS" ]; then
335+
echo "- **Python-affecting thrift CVEs: \`$PY_HITS\` — ACTION REQUIRED**"
336+
else
337+
echo "- Python-affecting thrift CVEs: none (all findings are non-Python bindings — accepted; see pyproject.toml)"
338+
fi
339+
} >> "$GITHUB_STEP_SUMMARY"
340+
341+
jq -r '.vulnerabilities[]?.cve | " \(.id): \([.descriptions[]?|select(.lang=="en")|.value][0][0:100])"' /tmp/thrift-nvd.json || true
342+
343+
if [ -n "$PY_HITS" ]; then
344+
echo "::error::Thrift CVE(s) mentioning Python detected ($PY_HITS) against locked thrift $THRIFT_VER. These are INVISIBLE to the OSV/purl gate. Re-evaluate the thrift pin (see the thrift note in pyproject.toml)."
345+
exit 1
346+
fi
347+
echo "No Python-affecting thrift CVE. Non-Python binding advisories remain accepted (0.23.0 fix blocked by ES-1960554)."
348+
267349
# --- Terminal: scheduled/manual event ---
268350
# Weekly reports ALL findings (not just CVSS >= 7) so emerging risk is
269351
# visible before it crosses the PR gate. PR-time is narrower to avoid

pyproject.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ python = "^3.10"
1919
# THRIFT-6067 / apache/thrift#3584) ships. The `DBR LTS Install` CI check
2020
# (.github/workflows/dbr-lts-install.yml) installs the built wheel on real DBR
2121
# LTS clusters and catches this regression when dependency pins change.
22+
#
23+
# SECURITY NOTE: thrift 0.22.0 IS affected by open Apache Thrift advisories
24+
# (CVE-2025-48431 and the CVE-2026-41602..41636 set), all fixed in 0.23.0.
25+
# We accept them here for two reasons:
26+
# (1) Apache Thrift is one monorepo shipping ~20 language libraries; the PyPI
27+
# `thrift` package is built only from `lib/py`. Each of these CVEs is in
28+
# a NON-Python binding -- verified against the upstream advisories:
29+
# Node.js (41636), Go (41602), c_glib/C (48431), Java (41603), Swift
30+
# (41604, 41605) -- so none touches the Python code paths we ship.
31+
# (2) The only fix (0.23.0) is the version that caused ES-1960554, so we
32+
# cannot take it until a build-safe thrift ships (see above).
33+
# NOTE these advisories are INVISIBLE to the OSV-Scanner gate: OSV and
34+
# Dependabot match by PyPI purl, but these CVEs are filed only against the
35+
# upstream CPE (cpe:2.3:a:apache:thrift) with no PyPI-package coordinate, so
36+
# neither reports them. This is a point-in-time, per-CVE determination -- a
37+
# FUTURE thrift CVE could land in `lib/py`. The weekly Security Scan therefore
38+
# runs a supplementary NVD-CPE check for thrift (see securityScan.yml) so a
39+
# Python-affecting thrift CVE surfaces instead of being silently missed.
2240
thrift = "~=0.22.0"
2341
pandas = [
2442
{ version = ">=1.2.5,<4.0.0", python = ">=3.10,<3.13" },

0 commit comments

Comments
 (0)