You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ingestion images ship a sqlparse that is affected by four advisories, and no version inside the declared ranges is clean — OSV reports fixed: 0.6.0 for all four, with no patched 0.5.x release.
Unescaped backslash breaks out of generated python/php string literals
0.6.0
The DoS advisories matter here because ingestion parses attacker-influenced SQL — query-log lineage and usage workflows feed arbitrary warehouse query history through sqlparse, so a single pathological statement can pin an ingestion worker.
Why the resolver cannot fix this
Three separate ceilings block sqlparse>=0.6.0, and all three are stale rather than substantive:
Source
Pin
Notes
collate-sqllineage 2.1.4 (ingestion/setup.py)
sqlparse==0.5.4
2.1.5 shipped sqlparse==0.6.0; 2.1.6 reverted only the pin to stay co-installable with dbt-core. The 2.1.5 and 2.1.6 wheels are byte-identical apart from the version string.
dbt-core, transitive via collate-data-diff
sqlparse<0.6.0
Every version including 1.12.2. The ceiling has been in place since the setup.py → pyproject.toml migration in Nov 2025 — nine months before 0.6.0 existed. Reported upstream: dbt-labs/dbt-core#15988
Airflow constraints-3.3.0/constraints-3.12.txt
sqlparse==0.5.5
Also vulnerable to all four. Applies to ingestion/Dockerfile via the openmetadata-managed-apis --constraint layer.
pip install dbt-core==1.12.2 'sqlparse>=0.6.0'
# ERROR: The conflict is caused by:
# dbt-core 1.12.2 depends on sqlparse<0.6.0 and >=0.5.5
Compatibility evidence
0.6.0 rewrote statement splitting onto a stack-based architecture, so this deserves scrutiny rather than a rubber stamp. Differential test of 0.5.4 vs 0.6.0 over 372 SQL statements scraped from our own unit tests, plus targeted cases for every 0.5.5/0.6.0 changelog entry:
is_safe_sql_query — 0 verdict changes across the 372-statement corpus plus 23 adversarial forbidden-SQL shapes chosen to exercise exactly the keywords 0.6.0 re-tokenizes (BEGIN, MATERIALIZED, END CASE, ROW_FORMAT, dollar-quotes). The guard is unaffected.
Lineage — 744 runs across SqlParseLineageAnalyzer and sqlfluff/ansi produced 7 differences, all improvements:
WITH x AS MATERIALIZED (...) no longer dies with ValueError: too many values to unpack (expected 2). Under 0.5.4 that query's lineage was lost entirely.
Lowercase as in CREATE TABLE t as SELECT f(x) FROM u now matches uppercase AS; 0.5.4 emitted u.f -> t.f, a column that does not exist.
The phantom <default>.materialized source table is gone.
Recovered lineage on a subquery CTAS that previously returned no sources.
mask_query — 383 queries, 1 difference, and it is a pre-existing bug rather than a regression: masker.py masks parser._parsed_result, a single statement, so any multi-statement query already loses all but the last statement under 0.5.4 (SELECT 1..; SELECT 2.. → only the 2nd). 0.6.0's corrected splitting merely adds BEGIN TRANSACTION; …; COMMIT; to the shapes that hit it. Masking never became weaker — nothing masked before is unmasked after. Related to the already-closed Masked Query in Lineage Registration Processes Only the First SQL Statement #19122.
collate-sqllineage's monkeypatch of sqlparse internals still applies intact — grouping.MAX_GROUPING_DEPTH/MAX_GROUPING_TOKENS raised 100×, KEYWORDS["STRING"] retyped to Name.Builtin, and the LATERAL VIEW EXPLODESQL_REGEX rewrite. This was the main silent-degradation risk: if a future sqlparse renames either grouping global, the patch becomes a no-op and lineage comes back quietly truncated with nothing failing.
Proposal
Override sqlparse to 0.6.0 in the image builds now, with a fail-closed import gate that asserts both the version and that the collate-sqllineage monkeypatch still bites — the CVEs are concrete and the ceilings are not.
Once dbt-labs/dbt-core#15988 lands, drop the override and raise the floor in ingestion/setup.py instead, which fixes it for everyone who installs openmetadata-ingestion from PyPI rather than only for our images.
Note this is a narrower, newer instance of the class of problem described in #26597.
Summary
The ingestion images ship a
sqlparsethat is affected by four advisories, and no version inside the declared ranges is clean — OSV reportsfixed: 0.6.0for all four, with no patched 0.5.x release.TokenList.__init__materializes O(subtree) per group — CPU DoSgroup_commentspython/phpstring literalsThe DoS advisories matter here because ingestion parses attacker-influenced SQL — query-log lineage and usage workflows feed arbitrary warehouse query history through
sqlparse, so a single pathological statement can pin an ingestion worker.Why the resolver cannot fix this
Three separate ceilings block
sqlparse>=0.6.0, and all three are stale rather than substantive:collate-sqllineage 2.1.4(ingestion/setup.py)sqlparse==0.5.4sqlparse==0.6.0; 2.1.6 reverted only the pin to stay co-installable with dbt-core. The 2.1.5 and 2.1.6 wheels are byte-identical apart from the version string.dbt-core, transitive viacollate-data-diffsqlparse<0.6.0setup.py→pyproject.tomlmigration in Nov 2025 — nine months before 0.6.0 existed. Reported upstream: dbt-labs/dbt-core#15988constraints-3.3.0/constraints-3.12.txtsqlparse==0.5.5ingestion/Dockerfilevia theopenmetadata-managed-apis --constraintlayer.Compatibility evidence
0.6.0 rewrote statement splitting onto a stack-based architecture, so this deserves scrutiny rather than a rubber stamp. Differential test of 0.5.4 vs 0.6.0 over 372 SQL statements scraped from our own unit tests, plus targeted cases for every 0.5.5/0.6.0 changelog entry:
is_safe_sql_query— 0 verdict changes across the 372-statement corpus plus 23 adversarial forbidden-SQL shapes chosen to exercise exactly the keywords 0.6.0 re-tokenizes (BEGIN,MATERIALIZED,END CASE,ROW_FORMAT, dollar-quotes). The guard is unaffected.SqlParseLineageAnalyzerand sqlfluff/ansi produced 7 differences, all improvements:WITH x AS MATERIALIZED (...)no longer dies withValueError: too many values to unpack (expected 2). Under 0.5.4 that query's lineage was lost entirely.asinCREATE TABLE t as SELECT f(x) FROM unow matches uppercaseAS; 0.5.4 emittedu.f -> t.f, a column that does not exist.<default>.materializedsource table is gone.mask_query— 383 queries, 1 difference, and it is a pre-existing bug rather than a regression:masker.pymasksparser._parsed_result, a single statement, so any multi-statement query already loses all but the last statement under 0.5.4 (SELECT 1..; SELECT 2..→ only the 2nd). 0.6.0's corrected splitting merely addsBEGIN TRANSACTION; …; COMMIT;to the shapes that hit it. Masking never became weaker — nothing masked before is unmasked after. Related to the already-closed Masked Query in Lineage Registration Processes Only the First SQL Statement #19122.grouping.MAX_GROUPING_DEPTH/MAX_GROUPING_TOKENSraised 100×,KEYWORDS["STRING"]retyped toName.Builtin, and theLATERAL VIEW EXPLODESQL_REGEXrewrite. This was the main silent-degradation risk: if a future sqlparse renames either grouping global, the patch becomes a no-op and lineage comes back quietly truncated with nothing failing.Proposal
Override
sqlparseto 0.6.0 in the image builds now, with a fail-closed import gate that asserts both the version and that the collate-sqllineage monkeypatch still bites — the CVEs are concrete and the ceilings are not.Once dbt-labs/dbt-core#15988 lands, drop the override and raise the floor in
ingestion/setup.pyinstead, which fixes it for everyone who installsopenmetadata-ingestionfrom PyPI rather than only for our images.Note this is a narrower, newer instance of the class of problem described in #26597.