Skip to content

Floor duckdb to 1.4.2 so a build cannot land on CVE-2025-64429 - #56

Merged
eddietejeda merged 1 commit into
mainfrom
floor-duckdb-cve-2025-64429
Oct 28, 2026
Merged

eddietejeda merged 1 commit into
mainfrom
floor-duckdb-cve-2025-64429

Conversation

@eddietejeda

Copy link
Copy Markdown
Contributor

A dependency scan flagged duckdb in the published image as Critical: "Attacker can abuse unchecked return values" — CVE-2025-64429. The block-based encryption added in duckdb 1.4.0 skips the return code of OpenSSL's rand_bytes(), so a failed generator reads as a good one. Affects 1.4.0–1.4.1; fixed in 1.4.2.

Nothing in the dependency graph asks for duckdb — neither hotdata 0.12.0 nor hotdata-langchain 0.17.0 declares it — so the unpinned install was whatever PyPI served the day the layer was built, and 1.4.x was current long enough to be baked in.

A floor, not a pin, next to urllib3's for the same reason: a rebuild today already resolves to 2.0.0, but a layer cache or a platform without current wheels would quietly drop back. Same floor in the local-dev install line in docs/operating.md, so a fresh venv can't reproduce it either.

Exposure was nil. server/server.py uses an in-memory duckdb.connect() only to cast JSONL to parquet — no ATTACH, no encryption keys — so the vulnerable path was never reached. This keeps the finding from coming back; it doesn't close an incident. The "Critical" badge is the scanner's, not the CVE's: upstream scores it AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N.

The scanner goes green once this merges and the image is rebuilt and republished.

Nothing in the dependency graph asks for duckdb -- not hotdata, not
hotdata-langchain -- so the unpinned install was whatever PyPI served the
day the layer was built, and 1.4.0-1.4.1 were current long enough to be
baked into a published image. Those skip the return code of OpenSSL's
rand_bytes() in the encryption path added in 1.4.0, so a failed generator
reads as a good one; 1.4.2 checks it. The server only casts JSONL to
parquet over an in-memory connection and never attaches an encrypted
database, so the path was unreachable here -- this keeps the scanner's
finding from coming back, it does not close an incident.

A floor, not a pin, and alongside urllib3's for the same reason: a
rebuild today already resolves past it, but a layer cache or a platform
without current wheels would quietly drop back. Same floor in the
local-dev install line, so a fresh venv cannot reproduce it either.
@eddietejeda
eddietejeda requested a review from a team as a code owner October 28, 2026 17:33
@eddietejeda
eddietejeda requested review from anoop-narang and removed request for a team October 28, 2026 17:33
Comment thread Dockerfile
# its job: nothing at runtime needs it, and its vendored copies of msgpack and
# setuptools are scanner findings of their own.
# hotdata` accepts versions with known CVEs. duckdb is floored for the same
# reason and against nothing: no dependency here asks for it, so an unpinned

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: The phrase "for the same reason and against nothing" contradicts the next clause (not blocking). The urllib3 reason is that hotdata accepts vulnerable versions. No dependency requests duckdb, so the duckdb reason differs. A reader cannot tell what "against nothing" means. Suggested wording: "duckdb is floored because no dependency here constrains it, so an unpinned duckdb is whatever PyPI served…"

@eddietejeda
eddietejeda merged commit d567268 into main Oct 28, 2026
2 checks passed
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.

1 participant