Skip to content

fix(security): bump apache-airflow 3.3.0 -> 3.3.1 for CVE-2026-67587 / CVE-2026-54183 - #31861

Closed
Khairajani wants to merge 4 commits into
mainfrom
fix/airflow-3.3.1-cve
Closed

fix(security): bump apache-airflow 3.3.0 -> 3.3.1 for CVE-2026-67587 / CVE-2026-54183#31861
Khairajani wants to merge 4 commits into
mainfrom
fix/airflow-3.3.1-cve

Conversation

@Khairajani

@Khairajani Khairajani commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

CVE-2026-67587 (High) -- the Task SDK rebuilt a Serde Callback by re-running its
constructor, which imports the module named by the stored callback path. SyncCallback
is an Airflow class, so it passes the default allowed_deserialization_classes
allow-list and tightening that setting does not help. A Dag author controls a task
instance's next_kwargs, so they can get an arbitrary module imported inside the
scheduler process when the awaiting_input timeout sweep deserializes that value. No
non-default configuration is required.

CVE-2026-54183 (Medium) -- the secrets masker's recursion-depth limit did not descend
into values nested inside a list, tuple or set, so a Variable holding a deeply nested
sensitive value rendered unmasked in the Variables UI. Anyone who can see the Variable
in the UI can already read it through the Variables REST API, so this is a
shoulder-surfing defense rather than a disclosure boundary -- hence Medium.

Both are fixed in 3.3.1 and nothing in the 3.3.0 line is clean. The pin, both base
image tags, the vendored constraints file and the integration-test image move together,
as they did for 3.2.2 -> 3.3.0 in #31338.

The constraints file is a straight re-download this time. It carried two hand-patches
marked "keep on regeneration" -- impyla and thrift at 0.24.0 for CVE-2026-66053 /
CVE-2026-41608 / CVE-2026-48586, against upstream constraints-3.3.0 shipping
impyla==0.22.0 and thrift==0.16.0 -- and upstream constraints-3.3.1 now ships both at
0.24.0 natively. Diffing the vendored 3.3.0 file against upstream constraints-3.3.0
confirms those two blocks were the only divergence, and the new file is byte-identical
to upstream constraints-3.3.1 outside comments. The comments are kept, reworded to say
the pin is now upstream-native, so a future regeneration off a branch that regressed
either version still gets caught.

Two comments that name a constraint were checked rather than blind-renumbered:

  • tests/integration/airflow/Dockerfile explains the constraints are deliberately not
    applied because they pin chardet against openmetadata-ingestion's chardet==4.0.0.
    Still true; the version moved 6.0.0.post1 -> 7.5.1, so the number is updated.
  • Dockerfile.ci's universal-pathlib workaround cites Airflow's >=0.3.8 floor.
    apache-airflow-core 3.3.1 still declares universal-pathlib>=0.3.8 and constraints
    still pin 0.3.10, so only the Airflow version in the prose changes.

Resolution verified with uv pip compile --python-version 3.12 --extra airflow:
apache-airflow==3.3.1 co-installs with every transitive floor pin in the airflow extra
(providers-http, -opensearch, -elasticsearch, tornado, Werkzeug, starlette,
python-multipart) with no conflict. sqlparse resolves to 0.5.4 there via
collate-sqllineage, unchanged by this PR -- the release images force 0.6.0 in
ingestion/operators/docker/Dockerfile, which does not consume this constraints file.

🤖 Generated with Claude Code

Greptile Summary

The PR upgrades the ingestion Airflow runtime from 3.3.0 to 3.3.1 to consume upstream security fixes.

  • Updates production, CI, and integration-test Airflow image tags and package pins.
  • Regenerates the vendored Airflow constraints file for 3.3.1.
  • Removes the obsolete Dagster croniter ceiling that conflicts with Airflow 3.3.1.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains.

No blocking failure remains.

Important Files Changed

Filename Overview
ingestion/Dockerfile Updates the production Airflow base image and upstream constraint URL to 3.3.1.
ingestion/Dockerfile.ci Updates the CI base image and all vendored constraint-file references to 3.3.1.
ingestion/airflow-constraints-3.3.1.txt Replaces the 3.3.0 constraints snapshot with the regenerated upstream 3.3.1 dependency set while preserving security-pin documentation.
ingestion/setup.py Pins the Airflow extra to 3.3.1 and removes a croniter ceiling incompatible with the new Airflow core requirement.
ingestion/tests/integration/airflow/Dockerfile Moves the lineage integration-test environment and explicit Airflow package pin to 3.3.1.
ingestion/tests/integration/airflow/conftest.py Aligns the integration fixture's declared Airflow base image with 3.3.1.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Airflow 3.3.1 package pin] --> B[Production ingestion image]
  A --> C[CI ingestion image]
  D[Airflow 3.3.1 constraints] --> B
  D --> C
  A --> E[Integration-test image]
  B --> F[OpenMetadata managed APIs]
  C --> F
  E --> G[Airflow integration tests]
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into fix/airflow-3.3..." | Re-trigger Greptile

Context used:

…CVE-2026-54183

CVE-2026-67587 (High) -- the Task SDK rebuilt a Serde `Callback` by re-running its
constructor, which imports the module named by the stored callback path. `SyncCallback`
is an Airflow class, so it passes the default `allowed_deserialization_classes`
allow-list and tightening that setting does not help. A Dag author controls a task
instance's `next_kwargs`, so they can get an arbitrary module imported inside the
scheduler process when the `awaiting_input` timeout sweep deserializes that value. No
non-default configuration is required.

CVE-2026-54183 (Medium) -- the secrets masker's recursion-depth limit did not descend
into values nested inside a list, tuple or set, so a Variable holding a deeply nested
sensitive value rendered unmasked in the Variables UI. Anyone who can see the Variable
in the UI can already read it through the Variables REST API, so this is a
shoulder-surfing defense rather than a disclosure boundary -- hence Medium.

Both are fixed in 3.3.1 and nothing in the 3.3.0 line is clean. The pin, both base
image tags, the vendored constraints file and the integration-test image move together,
as they did for 3.2.2 -> 3.3.0 in #31338.

The constraints file is a straight re-download this time. It carried two hand-patches
marked "keep on regeneration" -- impyla and thrift at 0.24.0 for CVE-2026-66053 /
CVE-2026-41608 / CVE-2026-48586, against upstream constraints-3.3.0 shipping
impyla==0.22.0 and thrift==0.16.0 -- and upstream constraints-3.3.1 now ships both at
0.24.0 natively. Diffing the vendored 3.3.0 file against upstream constraints-3.3.0
confirms those two blocks were the only divergence, and the new file is byte-identical
to upstream constraints-3.3.1 outside comments. The comments are kept, reworded to say
the pin is now upstream-native, so a future regeneration off a branch that regressed
either version still gets caught.

Two comments that name a constraint were checked rather than blind-renumbered:

- tests/integration/airflow/Dockerfile explains the constraints are deliberately not
  applied because they pin chardet against openmetadata-ingestion's chardet==4.0.0.
  Still true; the version moved 6.0.0.post1 -> 7.5.1, so the number is updated.
- Dockerfile.ci's universal-pathlib workaround cites Airflow's >=0.3.8 floor.
  apache-airflow-core 3.3.1 still declares `universal-pathlib>=0.3.8` and constraints
  still pin 0.3.10, so only the Airflow version in the prose changes.

Resolution verified with `uv pip compile --python-version 3.12 --extra airflow`:
apache-airflow==3.3.1 co-installs with every transitive floor pin in the airflow extra
(providers-http, -opensearch, -elasticsearch, tornado, Werkzeug, starlette,
python-multipart) with no conflict. sqlparse resolves to 0.5.4 there via
collate-sqllineage, unchanged by this PR -- the release images force 0.6.0 in
ingestion/operators/docker/Dockerfile, which does not consume this constraints file.
@Khairajani
Khairajani requested a review from a team as a code owner August 21, 2026 06:34
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — workflow failed

Validated commit 7cf7ec5398ab9f24dbb6848d6132329bd28cb07d in Playwright run 32463210944, attempt 1.

✅ 107 passed · ❌ 1 failed · 🟡 1 flaky · ⏭️ 1 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ❌ unmet · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 53m 45s

⏱️ Max setup 4m 53s · max shard execution 19m 1s · max shard-job elapsed before upload 25m 24s · reporting 6s

🌐 220.06 requests/attempt · 1.77 app boots/UI scenario · 0.00% common-shard skew

Optimization targets still in progress:

  • Browser traffic was 220.06 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 1.77 per UI scenario (216 boots / 122 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 46 0 0 0 0 0
🔴 Shard ingestion-01 25 1 1 1 0 0
✅ Shard ingestion-02 36 0 0 0 0 0

Genuine Failures (failed on all attempts)

Features/AutoPilot.spec.tsCreate Service and check the AutoPilot status (shard ingestion-01)
Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed  Locator: getByText('AutoPilot agents run completed successfully.') Expected: visible Timeout: 60000ms Error: element(s) not found  Call log: �[2m  - Expect "toBeVisible" with timeout 60000ms�[22m �[2m  - waiting for getByText('AutoPilot agents run completed successfully.')�[22m 
🟡 1 flaky test(s) (passed on retry)
  • Features/TestSuitePipelineRedeploy.spec.tsRe-deploy all test-suite ingestion pipelines (shard ingestion-01, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@Khairajani Khairajani added skip-pr-checks Bypass PR metadata validation check safe to test Add this label to run secure Github workflows on PRs labels Aug 21, 2026
ulixius9
ulixius9 previously approved these changes Aug 21, 2026
`uv pip install ingestion[all]` + `[test]` in the CI test environment fails to resolve
against apache-airflow 3.3.1:

    Because apache-airflow-core>=3.3.1 depends on croniter>=6.2.2 [...] and because
    openmetadata-ingestion[test]==2.0.0.0.dev0 depends on apache-airflow==3.3.1 and
    croniter<3, we can conclude that [...] requirements are unsatisfiable.

apache-airflow-core raised its croniter floor from >=2.0.2 to >=6.2.2 between 3.3.0 and
3.3.1, so the ceiling that used to co-exist with airflow now excludes it.

The ceiling is dead weight and predates this conflict -- it has been in the dagster
extra since #6416 and survived the #15679 dependency cleanup:

- dagster 1.13.18 (what `dagster_graphql>=1.8.0` resolves to) declares no croniter
  dependency at all; resolving dagster_graphql alone produces no croniter.
- Nothing under ingestion/ imports croniter. The only importer in the repo is
  openmetadata-airflow-apis, a separate distribution that does not declare it and picks
  it up transitively from airflow.
- That importer is already running croniter 6.2.x: constraints-3.3.0 pins croniter==6.2.2
  and the airflow images install under it, so 6.x compatibility for `croniter.is_valid` /
  `get_prev` is established by the shipped image, not assumed here. The call site is also
  behind an `is_airflow_3_or_higher()` guard and unreachable on Airflow 3.

Only the CI test environment resolved croniter 2.x, because it installs from the extras
without the constraints file. Removing the ceiling makes it match the images.

Verified with `uv pip compile --extra all --extra test` on both 3.10 and 3.12: resolves
to apache-airflow==3.3.1, croniter==6.2.4, dagster==1.13.18 with no conflict. This was
the only pin in the tree that collided with the airflow bump.
@gitar-bot

gitar-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Bumps Apache Airflow from 3.3.0 to 3.3.1 across base images, constraints, and integration tests to resolve CVE-2026-67587 and CVE-2026-54183. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile encountered an error while reviewing this PR. Please reach out to support@greptile.com for assistance and include this reference: e84ca658-4d62-416c-9284-78515c7c0aa7.

@Khairajani

Copy link
Copy Markdown
Contributor Author

Superseded by #31890, which carries this bump (with the croniter ceiling removal folded into the same commit) alongside the expat fix from #31757 as two separate commits. Combined because both are security fixes for the same image family with disjoint file sets.

@Khairajani Khairajani closed this Aug 21, 2026
auto-merge was automatically disabled August 21, 2026 12:51

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants