Add OSV-Scanner security gate + clear all CVEs (Python floor to 3.10)#798
Merged
Conversation
5 tasks
vikrantpuppala
had a problem deploying
to
azure-prod
July 2, 2026 06:54 — with
GitHub Actions
Failure
Single workflow, single job, three triggers:
- pull_request to main: fails on CVSS >= 7 findings only
(HIGH/CRITICAL block merges; MED/LOW visible but non-blocking)
- cron weekly (Sunday 00:00 UTC): reports ALL findings via email
- workflow_dispatch: behaves like cron
Mirrors the JDBC driver's security workflow (databricks-jdbc#1460)
adapted for Python:
- Reads poetry.lock natively via OSV-Scanner --lockfile (no
separate SBOM tool needed)
- Reuses the existing ./.github/actions/setup-jfrog composite action
for parity with other workflows (the workflow functionally doesn't
need JFrog since OSV reads the lockfile directly, but keeping the
composite action preserves the established pattern)
- Suppressions in osv-scanner.toml ([[IgnoredVulns]] schema)
The workflow is not yet wired into branch protection. Day-one scan
against current main surfaces 14 HIGH / 10 MED / 1 LOW (25 total) --
concentrated in cryptography, urllib3, pyjwt, pyarrow, requests,
black, pytest, python-dotenv, idna. These will be addressed by a
follow-up dep-bump PR.
Co-authored-by: Isaac
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
Port the fail-closed hardening from the Go (#362) and Node (#388) OSV workflows, and refresh poetry.lock so the gate passes with zero suppressions. securityScan.yml hardening (was fail-open in three places): - Capture osv-scanner's exit code; tolerate only 0/1 and fail closed on any other code (network error, corrupt binary) instead of masking it with `|| true`. - Validate the output is well-formed JSON with a .results array before parsing, so a truncated/partial scan fails closed rather than parsing to zero findings. - Resolve empty group max_severity via a cvss_num fallback to an UNKNOWN sentinel (using `try (x|tonumber) catch null`, not `tonumber?`), so a scoreless finding can never sort to 0 and sail past the CVSS>=7 gate. UNKNOWN always blocks (PyPA advisories carry CVSS; a scoreless finding is a GHSA-only/malware advisory). - Integer-count guards fail closed on parse failure. - Drop per-repo SMTP email in favor of artifact upload for the planned cross-repo collator (parity with Go/Node). CVE clearing WITHOUT forcing dependency floors: - Bump the Python floor to ^3.10. The CVE-fixed cryptography (>=46) and pyjwt (>=2.12) require Python >=3.10 upstream, so a single CVE-clean lockfile cannot span 3.8/3.9. This is the only breaking change. - All runtime dependency pins are UNCHANGED (thrift ~=0.22.0, urllib3 >=1.26, requests ^2.18.1, pyjwt ^2.0.0, pyarrow floors). The existing constraints already ALLOW the CVE-free versions; the refreshed lock simply resolves to them (urllib3 2.7.0, cryptography 49.0.0, pyarrow 23.0.1, requests 2.34.2, pyjwt 2.13.0, idna 3.18, python-dotenv 1.2.2). Customers do not need us to relax or raise any pin to become CVE-free. - thrift stays ~=0.22.0 (no known advisory; the <0.23 cap avoids the ES-1960554 DBR-LTS install break). - Bump dev-only black ^22 -> ^26 and pytest ^7 -> ^9 to clear their advisories (never shipped in the wheel); reformat src with black 26. Result: OSV-Scanner v2.3.8 reports 0 findings on the refreshed lock; osv-scanner.toml needs no suppressions. Co-authored-by: Isaac Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
vikrantpuppala
force-pushed
the
vp/security-scan
branch
from
July 16, 2026 16:04
c1ddd69 to
02f2f6b
Compare
vikrantpuppala
had a problem deploying
to
azure-prod
July 16, 2026 16:04 — with
GitHub Actions
Error
The pyproject floor is now ^3.10, so 3.9 legs can no longer `poetry install` (^3.10 is unsatisfiable on a 3.9 interpreter) and would fail. Remove "3.9" from every unit-test / lint / type-check / pyarrow / kernel matrix in code-quality-checks.yml and warm-deps-cache.yml, and drop the now-moot 3.9-kernel exclude in the warm-deps cache. Co-authored-by: Isaac Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:06 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 16:07 — with
GitHub Actions
Inactive
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>
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:27 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:29 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:29 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:29 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:29 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
vikrantpuppala
temporarily deployed
to
azure-prod
July 16, 2026 17:50 — with
GitHub Actions
Inactive
gopalldb
approved these changes
Jul 17, 2026
thrift 0.24.0 shipped (THRIFT-6067) after this PR was opened. It is the first release that both clears the open Apache Thrift CVEs (CVE-2025-48431 + the CVE-2026-41602..41636 set, all fixed in 0.23.0) AND is safe to install on DBR LTS: unlike the yanked 0.23.0 (sdist-only, setup.py sys.exit(0) → SEV0 ES-1960554), 0.24.0 ships prebuilt manylinux2014 wheels (cp310-cp314) + macOS/musl/Windows, so pip installs a wheel and never runs setup.py -- the ES-1960554 build break cannot trigger. Gated on the DBR LTS Install CI check. Supersedes the earlier "hold at ~=0.22.0 and accept the thrift CVEs as non-Python-binding" stance now that a build-safe fixed thrift exists. The supplementary NVD-CPE thrift watch is no longer needed and is removed. Lockfile regenerated: thrift 0.24.0; all other CVE deps unchanged and clean. OSV-Scanner: 0 findings. Co-authored-by: Isaac Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Failure
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
vikrantpuppala
had a problem deploying
to
azure-prod
July 20, 2026 08:34 — with
GitHub Actions
Error
The weekly NVD-CPE thrift watch existed only because we were accepting the thrift CVEs on the 0.22.0 pin (filed against the CPE, not the PyPI purl, so the OSV gate couldn't see them). With thrift bumped to 0.24.0 those CVEs are actually cleared, so the watch has nothing left to guard. Remove it; the normal OSV gate + version pin handle any future thrift CVE. Co-authored-by: Isaac Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
There was a problem hiding this comment.
Verdict: 1 Medium · 1 Low
Solid, well-documented security gate; the fail-closed logic (exit-code classification, JSON validation, integer-count guards, UNKNOWN-always-blocks) is sound. Two non-blocking items: the scanner binary is executed without checksum verification (medium — it's the gate's root of trust and the rest of the workflow SHA-pins its actions), and the findings sort mis-places always-blocking UNKNOWN entries (low, display-only). The poetry.lock refresh and Python-floor bump to 3.10 look internally consistent with the CI matrix changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds the OSV-Scanner security gate and clears all open dependency CVEs on the connector — without forcing any dependency-pin changes on consumers. The only breaking change is raising the Python floor to 3.10, which is required because the CVE-fixed
cryptographyandpyjwtreleases are not installable on 3.8/3.9.What it does
1. OSV-Scanner security workflow (
securityScan.yml), hardened fail-closedpoetry.locknatively.|| true..resultsarray before parsing (partial/corrupt scan → fail closed, not "0 findings").max_severityvia acvss_numfallback to anUNKNOWNsentinel (usingtry (x|tonumber) catch null, nottonumber?) so a scoreless finding can never sort to 0 and sail past the gate.UNKNOWNalways blocks.2. Clears all CVEs by refreshing
poetry.lock— no forced pin changesthrift ~=0.22.0,urllib3 >=1.26,requests ^2.18.1,pyjwt ^2.0.0,pyarrowfloors). The existing constraints already allow the CVE-free versions; the refreshed lock simply resolves to them:urllib3 2.7.0,cryptography 49.0.0,pyarrow 23.0.1,requests 2.34.2,pyjwt 2.13.0,idna 3.18,python-dotenv 1.2.2.3. Raises the Python floor to
^3.10(the only breaking change)cryptography(≥46) andpyjwt(≥2.12) require Python ≥3.10 upstream, so a single CVE-clean lockfile cannot span 3.8/3.9. Both are long past EOL (3.8 EOL 2024-10, 3.9 EOL 2025-10) and no supported DBR LTS is affected. CI matrices updated to drop 3.9;Requires-Pythonfails safe for anyone still on 3.9 (they stay on 4.3.x).4.
thriftstays~=0.22.0, documented accuratelylib/pycode we ship is not affected. The only fix (0.23.0) is the version that caused the SEV0 ES-1960554 DBR-LTS install break, so we cannot take it until a build-safe thrift ships (THRIFT-6067).cpe:2.3:a:apache:thriftwith no package coordinate). A supplementary weekly NVD-CPE thrift watch in the workflow surfaces them and hard-fails if a Python-affecting thrift CVE ever appears. 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.5. Dev-tool + test fixes surfaced by the refresh
black^22 → ^26 andpytest^7 → ^9 to clear their advisories (never shipped in the wheel); reformatsrcwith black 26.auth/oauth.py,auth/retry.py) — type-annotation-only.pytzas an explicit dev dependency (pandas 3.0 dropped it as a required dep;test_parameters.pyimports it directly).Result
osv-scanner.tomlneeds no suppressions.black --checkpasses; mypy passes; the Python matrix (3.10–3.14) is green.Test plan
poetry.lock→ 0 findings, 0 blocking.black --check srcpasses with black 26.5.1.mypy srcpasses (2 pre-existing latent errors fixed).This pull request and its description were written by Isaac.