Skip to content

fix(security): pull expat 2.8.3-1~deb13u1 into the ingestion-base image - #31757

Closed
Khairajani wants to merge 5 commits into
mainfrom
fix/expat-cve-2026-72522
Closed

fix(security): pull expat 2.8.3-1~deb13u1 into the ingestion-base image#31757
Khairajani wants to merge 5 commits into
mainfrom
fix/expat-cve-2026-72522

Conversation

@Khairajani

@Khairajani Khairajani commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What

Adds expat to the existing dpkg source-package upgrade in the late root layer of ingestion/operators/docker/Dockerfile and Dockerfile.ci.

Why

The image reports expat 2.8.2 for CVE-2026-72522 (DSA-6446-1 — out-of-bounds read and resultant infinite loop in libexpat's *_toUtf16 surrogate handling). trixie-security has 2.8.3-1~deb13u1.

expat is not in the python:3.12-slim-trixie base at all — it arrives transitively from the top-of-file apt-get install. That layer is exactly why the image is stuck at 2.8.2: its cache key never changes, so it keeps resolving against the Debian index that was current when it was first built. Adding expat there would freeze the fix the same way.

It goes in the late root layer instead, below the COPY and pip layers, where the index is re-read on every build — the same reasoning that put util-linux there.

How

expat rides in the existing dpkg query rather than a second RUN, so one apt call covers both source packages and the next OS CVE is a one-line edit:

ul="$(dpkg-query -W -f='${source:Package} ${Package}\n' | awk '$1=="util-linux"{print $2}')"; \
[ -n "$ul" ] || { echo "no src:util-linux packages found; refusing to skip the CVE patch" >&2; exit 1; }; \
ex="$(dpkg-query -W -f='${source:Package} ${Package}\n' | awk '$1=="expat"{print $2}')"; \
apt-get -qq install -y --only-upgrade $ul $ex; \

The package set stays computed from dpkg rather than hand-listed, for the reason already documented there: scanners report each binary of a source package separately, so a hand-written list silently leaves one behind.

util-linux keeps its non-empty assert and expat deliberately does not get one. util-linux is Essential, so an empty query there means dpkg-query misbehaved and the build must stop. expat is transitive, so an empty query is a legitimate image with nothing to patch — asserting it would break the build for no reason. Asserting one of the two still covers the hazard the check exists for: apt-get install --only-upgrade with no package arguments exits 0, so an all-empty query would give a green build that shipped the vulnerable packages.

Dockerfile.ci carries its own copy of this block and gets the same change — it is the base that Collate's Snyk scan builds from.

Verification

Ran the RUN block verbatim in a real build layer on python:3.12-slim-trixie:

package before after
libexpat1 2.7.1-2 2.8.3-1~deb13u1
all nine util-linux binaries 2.41-5 2.41.5-0+deb13u1

Exit 0. The expat-absent path was exercised separately on the bare base and also exits 0, upgrading util-linux alone — that path is real, since the base ships no expat.

Out of scope, deliberately

ingestion/Dockerfile is untouched because there is nothing to upgrade to, not because it is clean. apache/airflow:3.3.0-python3.12 is bookworm; Debian's tracker still marks bookworm and bookworm-security vulnerable, and the image already carries 2.5.0-1+deb12u2 — the newest build either suite offers. Needs revisiting when Debian ships a bookworm fix.

Related

Collate-side half: open-metadata/openmetadata-collate#5909 — the two must land together, or the collate image keeps shipping what the base tag was pinned to.

🤖 Generated with Claude Code

Greptile Summary

Adds expat binaries to the existing late-layer Debian security upgrade so ingestion-base images receive the fixed package from trixie-security.

  • Queries installed binaries originating from the expat source package.
  • Upgrades expat and util-linux binaries in one apt invocation.
  • Applies the same change to production and CI ingestion-base Dockerfiles.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
ingestion/operators/docker/Dockerfile Adds installed expat binaries to the late security-upgrade layer without changing the valid expat-absent path.
ingestion/operators/docker/Dockerfile.ci Mirrors the ingestion-base expat security upgrade in the CI image definition.

Reviews (5): Last reviewed commit: "Merge branch 'main' into fix/expat-cve-2..." | Re-trigger Greptile

The image reports expat 2.8.2 for CVE-2026-72522 (DSA-6446-1: out-of-bounds
read and resultant infinite loop in libexpat's *_toUtf16 surrogate handling);
trixie-security has 2.8.3-1~deb13u1. expat is not in the python:3.12-slim-trixie
base at all -- it comes in transitively from the top-of-file apt install -- and
that layer is exactly why the image is stuck at 2.8.2: its cache key never
changes, so it keeps resolving against the Debian index that was current when it
was first built. Adding expat there would freeze the fix the same way. It goes
in the late root layer instead, below the COPY and pip layers, where the index
is re-read on every build -- the same reasoning that put util-linux there.

expat rides in the existing dpkg source-package query rather than a second RUN,
so one apt call covers both source packages and the next OS CVE is a one-line
edit. The package set stays computed from dpkg rather than hand-listed for the
reason already documented there: scanners report each binary of a source package
separately, so a hand-written list silently leaves one behind.

util-linux keeps its non-empty assert and expat deliberately does not get one.
util-linux is Essential, so an empty query there means dpkg-query misbehaved and
the build must stop; expat is transitive, so an empty query is a legitimate
image with nothing to patch and failing on it would break the build for no
reason. Asserting one of the two still covers the hazard the check exists for:
`apt-get install --only-upgrade` with no package arguments exits 0, so an
all-empty query would give a green build that shipped the vulnerable packages.

Verified in a real build layer on python:3.12-slim-trixie: libexpat1 2.7.1-2 ->
2.8.3-1~deb13u1 and all nine util-linux binaries -> 2.41.5-0+deb13u1, exit 0.
The expat-absent path was exercised on the bare base and also exits 0,
upgrading util-linux alone.

ingestion/Dockerfile gets no equivalent change because there is nothing to
upgrade to, not because it is clean: apache/airflow:3.3.0-python3.12 is
bookworm, Debian still marks bookworm and bookworm-security vulnerable, and the
image already carries 2.5.0-1+deb12u2 -- the newest build either suite offers.
It needs revisiting when Debian ships a bookworm fix.
@Khairajani
Khairajani requested a review from a team as a code owner August 19, 2026 10:29
@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 19, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 1a5198a21a68cbdb72f98dfb8b7eb260dc7d05e8 in Playwright run 32463270593, attempt 1.

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

Performance

Blocking targets: ✅ met · 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) 48m 33s

⏱️ Max setup 4m 16s · max shard execution 12m 28s · max shard-job elapsed before upload 17m 46s · reporting 5s

🌐 216.26 requests/attempt · 1.79 app boots/UI scenario · 0.00% common-shard skew

Optimization targets still in progress:

  • Browser traffic was 216.26 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 1.79 per UI scenario (216 boots / 121 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 33 0 0 0 0 0
✅ Shard ingestion-02 31 0 0 0 0 0

📦 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 safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Aug 19, 2026
@Khairajani Khairajani added the To release Will cherry-pick this PR into the release branch label Aug 19, 2026
@Khairajani
Khairajani enabled auto-merge August 19, 2026 12:01
@Khairajani
Khairajani added this pull request to the merge queue Aug 20, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-08-20T12:05:58Z)

Blocked the queue: py-tests-status

  • py-tests-postgres — py-tests-status, python / Verify Expected Jobs, python / Integration Tests (shard-3)

@sonarqubecloud

Copy link
Copy Markdown

@Khairajani
Khairajani added this pull request to the merge queue Aug 20, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-08-20T22:20:40Z)

Blocked the queue: py-tests-status, py-tests-status

  • PostgreSQL PR RDF E2E Tests — Playwright RDF (Knowledge Graph + Ontology), RDF Playwright execution
  • py-tests-postgres — py-tests-status, python / Verify Expected Jobs, python / Integration Tests (shard-2), python / Integration Tests (shard-2), python / Integration Tests (shard-2)
  • py-tests — py-tests-status, python / Verify Expected Jobs, python / Integration Tests (shard-2), python / Integration Tests (shard-2), python / Integration Tests (shard-2)
  • Postgresql PR Playwright E2E Tests — playwright / playwright-ci (chromium-14)

@Khairajani
Khairajani added this pull request to the merge queue Aug 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-08-21T05:58:24Z)

Blocked the queue: playwright-summary

@Khairajani
Khairajani added this pull request to the merge queue Aug 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-08-21T08:12:33Z)

Blocked the queue: py-tests-status, py-tests-status

  • py-tests — py-tests-status, python / Verify Expected Jobs, python / Integration Tests (shard-2), python / Integration Tests (shard-2), python / Integration Tests (shard-2)
  • py-tests-postgres — py-tests-status, python / Verify Expected Jobs, python / Integration Tests (shard-2), python / Integration Tests (shard-2), python / Integration Tests (shard-2), python / Integration Tests (shard-3)

@gitar-bot

gitar-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Pulls expat 2.8.3-1~deb13u1 into the ingestion-base and CI Dockerfiles to resolve CVE-2026-72522. 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

@Khairajani

Copy link
Copy Markdown
Contributor Author

Superseded by #31890, which carries this expat fix alongside the airflow 3.3.1 bump from #31861 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 To release Will cherry-pick this PR into the release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants