Skip to content

chore(deps): Bump sqlparse to 0.6.0 to clear pip-audit findings - #120

Merged
m1so merged 1 commit into
mainfrom
chore/deps-audit-2026-08-24
Aug 25, 2026
Merged

chore(deps): Bump sqlparse to 0.6.0 to clear pip-audit findings#120
m1so merged 1 commit into
mainfrom
chore/deps-audit-2026-08-24

Conversation

@tkislan

@tkislan tkislan commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

pip-audit was failing on four new advisories in sqlparse 0.5.5, all fixed only in 0.6.0. Unlike the previous audit PRs, sqlparse is a direct dependency (# SQL templating, pyproject.toml:85) and the repo's own <0.6 cap was what blocked the fix — so this bumps that constraint in place rather than adding an entry to the transitive security-constraint block.

The lock moves sqlparse and nothing else.

Changes

pyproject.toml — direct constraint bump

     # SQL templating
     "jinja2>=3.1.6,<4",
-    "sqlparse>=0.4.4,<0.6",
+    "sqlparse>=0.6.0,<0.7",
     "pymysql>=1.1.1,<1.2",

<0.7 follows the floor-plus-one-minor style used for the other security bumps (cryptography>=50.0.0,<51).

poetry.lock — one package moved

 name = "sqlparse"
-version = "0.5.5"
+version = "0.6.0"
-python-versions = ">=3.8"
+python-versions = ">=3.10"

.github/workflows/ci.yml — drop two dead ignore entries

-          # PYSEC-2023-121 (CVE-2022-4899 / GHSA-5c9c-6x87-f9vm)
-          # * incorrectly flags zstd versions >= 1.5.4.0 as vulnerable to CVE-2022-4899
-          # * see https://github.com/pypa/advisory-database/... (our version ranges are outside of reported versions)
-          # CVE-2026-0994 (protobuf DoS via nested Any messages in ParseDict)
-          # * no fix version available yet
-          # * low risk: only affects json_format.ParseDict() with untrusted input
           # PYSEC-2024-161 (pyarrow deserialization vulnerability)
           ...
           ignore-vulns: &ignore-vulns |
-            PYSEC-2023-121
-            CVE-2026-0994
             PYSEC-2024-161
             PYSEC-2026-113

zstd 1.5.7.2 and protobuf 5.29.6 now return zero advisories at every pinned version across all Python marker branches, so those two suppressions matched nothing. The two pyarrow entries are retained — they still apply to pyarrow 16.1.0 on Python 3.10/3.11.

Why <0.6 was there, and why it's safe to lift

The cap was never about 0.6 — 0.6.0 did not exist when it was written. It dates from the open-source commit 8b2941b (2025-10-30), when the newest sqlparse was 0.5.3; 0.6.0 shipped 2026-08-13. The line was untouched in between:

$ git log --all --oneline -G'sqlparse>=' -- pyproject.toml
8b2941b Open source Deepnote Toolkit          <- "sqlparse>=0.4.4,<0.6"

So it was a routine next-minor ceiling for a 0.x package, matching the repo's other 0.x caps (db-dtypes<1.4, clickhouse-sqlalchemy<0.4, pyathena<4). That caution was earned — this repo was bitten by a sqlparse bump before:

8b5825f chore(deps): Bump sqlparse from 0.5.3 to 0.5.4 (#69)
65e194d fix: Revert sqlparse parsing limits to pre-0.5.4 defaults (#77)

0.5.4 introduced MAX_GROUPING_TOKENS=10000, which broke wide analytical queries; configure_sqlparse_limits() exists because of that incident. Worth noting that CVE-2026-54284 was fixed in sqlparse/sql.py, not by touching the caps — MAX_GROUPING_TOKENS / MAX_GROUPING_DEPTH keep the same names, module, defaults and is not None semantics in 0.6.0, so the #77 workaround is unaffected.

The only breaking change declared in the 0.6.0 CHANGELOG is dropping Python 3.8/3.9; this repo is requires-python = ">=3.10.0,<3.14". tokens.py and exceptions.py are byte-identical between the two versions, and sqlparse.parse keeps its signature.

Per-advisory assessment

Entry point for all of these is sql_execution.py:78, which calls unchain_sql_query() on raw cell text before Jinja rendering — so the parser sees the SQL first, ahead of validation and any DB connection. One cell execution parses the same text several times (sql_query_chaining.py:15,26,73,132,207, sql_execution.py:209, sql_caching.py:35), multiplying any per-parse cost.

Advisory What Reachable here?
PYSEC-2026-3696
CVE-2026-59894
Unescaped backslashes in the python/php output filters let crafted SQL break out of the generated string literal No. The repo never calls sqlparse.format(..., output_format=...) — zero hits for output_format, OutputPythonFilter, OutputPHPFilter across deepnote_toolkit/, deepnote_core/, installer/, tests/. google-cloud-spanner calls sqlparse.format(query, strip_comments=True) only (spanner_dbapi/parse_utils.py:197,228), not the codegen filters. Fixed as a side effect of the bump.
PYSEC-2026-3697
CVE-2026-71491
group_comments is O(n²) on comment-only statements; reachable via sqlparse.parse() and format(strip_comments=True) Yes — reproduced. Both the repo's parse() sites and spanner's strip_comments=True path are exposed.
PYSEC-2026-3698
CVE-2026-59893
ReDoS in the dollar-quoted literal lexer (keywords.py:33, backreference \1) Yes — reproduced. This one is in the lexer, upstream of grouping in filter_stack.py (:31 tokenize → :41 group), so the grouping caps provide zero mitigation even at their strictest setting. Dialect-irrelevant: sqlparse loads every keyword dict into one process-wide regex list and the repo never passes dialect info.
PYSEC-2026-3699
CVE-2026-54284
TokenList.__init__ flattens the whole subtree per group, burning CPU before the depth/token caps trip Yes — reproduced.

Measured impact (0.5.5 → 0.6.0)

Same machine, limits configured exactly as the toolkit sets them at runtime (MAX_GROUPING_TOKENS=None, MAX_GROUPING_DEPTH=None — see sql_utils.py:32-33, applied by runtime_initialization.py:58):

Payload 0.5.5 0.6.0
benign 994 B query 0.009 s 0.006 s
8000 comment lines (39 KB), parse3697 9.307 s 0.062 s
8000 comment lines, format(strip_comments=True)3697 9.947 s 0.077 s
8000 space-separated $t<i>$ openers (61 KB) — 3698 3.580 s 0.245 s
nesting depth 1500 (2 KB), parse3699 2.729 s 0.024 s

All three DoS advisories show the same shape: quadratic on 0.5.5, linear on 0.6.0.

  • 3697: 2000 lines → 0.583 s, 8000 → 9.307 s (4× input, 16× time).
  • 3698: 1000 → 0.068 s, 2000 → 0.241 s, 4000 → 0.886 s, 8000 → 3.580 s on 0.5.5, versus 0.027 / 0.058 / 0.117 / 0.245 s on 0.6.0 — clean quadratic becoming clean linear, 14.6× at 61 KB.
  • 3699: matches the advisory's "seconds of CPU from a ~2 KB payload" claim.

Correction on 3698. My first payload used adjacent openers ($tag0$$tag1$…), which accidentally forms $$ empty-tag delimiters that the regex matches immediately — it measured linear on both versions and I initially recorded 3698 as unreproduced. Space-separating the openers removes the $$ pairs and reproduces the advisory cleanly, as shown above. The numbers in the table are from the corrected payload.

Known behavior change (not a blocker)

0.6.0 promotes MATERIALIZED and ROW_FORMAT to reserved keywords. extract_table_reference_from_token (sql_query_chaining.py:59-63) discards Keyword-typed tokens, so a SQL block whose variable name is exactly materialized or row_format silently stops being chained via find_query_preview_references:

                                     0.5.5              0.6.0
SELECT * FROM materialized        ['materialized']   []
SELECT * FROM row_format          ['row_format']     []
SELECT * FROM my_materialized_view  ['my_...view']   ['my_...view']   (unaffected)
SELECT * FROM select              []                 []               (already broken)

The unit suite does not cover this. It is a pre-existing class of limitation — a block named select or case fails identically on 0.5.5 today; the reserved-word list just grew by two. Fixing it properly means not discarding keyword tokens in the expect_table position, which is a behavior change beyond this PR. Worth knowing if someone reports a chaining break after this lands.

Follow-up on the disabled grouping caps (unchanged by this PR): #121.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QSHPq7nj9cJD8XVPesADtA

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 26f8fdda-da1b-4e00-b343-7e447a159be9

📥 Commits

Reviewing files that changed from the base of the PR and between c0d036d and 90e4f13.

📒 Files selected for processing (1)
  • pyproject.toml

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.


📝 Walkthrough

Walkthrough

The pull request updates the sqlparse dependency constraint to >=0.6.0,<0.7. It also removes production audit ignores for PYSEC-2023-121 and CVE-2026-0994. Existing ignores remain unchanged.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Merge Risk: ⚪ Minimal · up to 90e4f

This dependency-only update and cleanup are merge-ready after normal checks; no actionable merge-blocking risk remains.

Suggested reviewers: m1so, mfranczel

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Updates Docs ✅ Passed The patch only updates sqlparse, the lockfile, and CI audit suppressions; it implements no feature that requires documentation or roadmap updates.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: upgrading sqlparse to 0.6.0 to resolve pip-audit findings.

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown

📦 Python package built successfully!

  • Version: 2.5.0.dev2+050c323
  • Wheel: deepnote_toolkit-2.5.0.dev2+050c323-py3-none-any.whl
  • Install:
    pip install "deepnote-toolkit @ https://deepnote-staging-runtime-artifactory.s3.amazonaws.com/deepnote-toolkit-packages/2.5.0.dev2%2B050c323/deepnote_toolkit-2.5.0.dev2%2B050c323-py3-none-any.whl"

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 24, 2026
@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.46%. Comparing base (2d60c22) to head (90e4f13).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #120   +/-   ##
=======================================
  Coverage   74.46%   74.46%           
=======================================
  Files          95       95           
  Lines        5707     5707           
  Branches      851      851           
=======================================
  Hits         4250     4250           
  Misses       1180     1180           
  Partials      277      277           
Flag Coverage Δ
combined 74.46% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@deepnote-bot

deepnote-bot commented Aug 24, 2026

Copy link
Copy Markdown

🚀 Review App Deployment Started

📝 Description 🌐 Link / Info
🌍 Review application ra-120
🔑 Sign-in URL Click to sign-in
📊 Application logs View logs
🔄 Actions Click to redeploy
🚀 ArgoCD deployment View deployment
Last deployed 2026-08-24 17:09:51 (UTC)
📜 Deployed commit 944f67aa491a041d90022b632f4d89a4fdf6a1e3
🛠️ Toolkit version 050c323

sqlparse 0.5.5 is affected by four advisories, all fixed only in 0.6.0:

  PYSEC-2026-3696  codegen escaping breakout in the python/php output filters
  PYSEC-2026-3697  quadratic group_comments (comment-only statements)
  PYSEC-2026-3698  ReDoS in the dollar-quoted literal lexer
  PYSEC-2026-3699  TokenList.__init__ flattens the subtree per group

sqlparse is a direct dependency, so this bumps its constraint in place
rather than adding an entry to the transitive security-constraint block.
Nothing else caps it below 0.6.0 (google-cloud-spanner asks for >=0.4.4),
so the lock moves sqlparse alone.

Also drops two ignore-vulns entries that no longer match any pinned
version: PYSEC-2023-121 (zstd) and CVE-2026-0994 (protobuf). The pyarrow
entries stay - they still apply to pyarrow 16.1.0 on Python 3.10/3.11.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QSHPq7nj9cJD8XVPesADtA
@tkislan
tkislan marked this pull request as ready for review August 24, 2026 17:45
@tkislan
tkislan requested a review from a team as a code owner August 24, 2026 17:45
@tkislan
tkislan requested review from m1so and mfranczel August 24, 2026 17:45
@m1so
m1so merged commit c3950bb into main Aug 25, 2026
33 checks passed
@m1so
m1so deleted the chore/deps-audit-2026-08-24 branch August 25, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants