Commit 1148152
authored
Add OSV-Scanner security gate + clear all CVEs (Python floor to 3.10) (#798)
* Add OSV-Scanner-based security workflow
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>
* Harden OSV gate (fail-closed) + refresh lockfile to clear all CVEs
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>
* ci: drop Python 3.9 from CI matrices to match the ^3.10 floor
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>
* 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>
* fix(types): resolve 2 mypy errors surfaced by the refreshed mypy
The lockfile refresh floats mypy (^1.10.1) up to 1.20.2, which is stricter
and flags two pre-existing latent type issues that the older mypy missed:
- auth/oauth.py:48 — is_expired() returned `exp_time and (...)`, whose value
is `Any | None` (the exp claim) when falsy, not bool, violating the
`-> bool` annotation. Use `exp_time is not None and (...)` so the return
is a real bool and the None-exp case is explicit.
- auth/retry.py:248 — the command_type setter was annotated
`value: CommandType`, but the getter returns `Optional[CommandType]` and
__private_init__ assigns an `Optional[CommandType]`. Widen the setter to
`Optional[CommandType]` to match the getter and actual usage.
Both are type-annotation-only changes; no runtime behavior change.
Co-authored-by: Isaac
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
* fix(tests): declare pytz explicitly (pandas 3.0 dropped it as a hard dep)
tests/unit/test_parameters.py imports pytz directly. It previously arrived
transitively via pandas, but the refreshed lock resolves pandas 3.0.3 on
Python >=3.11, and pandas 3.0 removed pytz from its required dependencies
(it is now only a pandas extra). That broke test collection on 3.11+ with
`ModuleNotFoundError: No module named 'pytz'`.
Add pytz as an explicit dev dependency so the test suite no longer relies on
pandas's transitive graph, which differs across the Python matrix.
Co-authored-by: Isaac
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
* Bump thrift to ~=0.24.0 (CVE-clean + DBR-LTS-safe via wheels)
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>
* Remove the supplementary thrift NVD-CPE watch (obsolete after 0.24.0)
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>
---------
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>1 parent 9f81d35 commit 1148152
20 files changed
Lines changed: 1717 additions & 1308 deletions
File tree
- .github/workflows
- src/databricks/sql
- auth
- backend
- sea/utils
- common
- telemetry
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
99 | | - | |
| 99 | + | |
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| |||
246 | 246 | | |
247 | 247 | | |
248 | 248 | | |
249 | | - | |
| 249 | + | |
250 | 250 | | |
251 | 251 | | |
252 | 252 | | |
| |||
273 | 273 | | |
274 | 274 | | |
275 | 275 | | |
276 | | - | |
| 276 | + | |
277 | 277 | | |
278 | 278 | | |
279 | 279 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| |||
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | 101 | | |
106 | 102 | | |
107 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
0 commit comments