Skip to content

Baked sqlite_scanner extension version mismatch with shipped DuckDB runtime #185

@STU-Cypfer

Description

@STU-Cypfer

Summary

The openrelik-server image ships a pre-baked /app/openrelik/sqlite_scanner.duckdb_extension binary compiled for DuckDB v1.4.4, but the duckdb Python package installed in the same image is v1.5.2. Any code path that LOADs the baked file hits:

IO Error: Failed to install '/app/openrelik/sqlite_scanner.duckdb_extension'
The file was built specifically for DuckDB version 'v1.4.4' and can only be
loaded with that version of DuckDB. (this version of DuckDB is 'v1.5.2')

Reproduction

Latest image as of 2026-04-23:

ghcr.io/openrelik/openrelik-server@sha256:89adb0ebc41f5fbb1296a098c1e440c1761e896aaa0e4be2169dc16eed3a8785

Inside the container:

$ python3 -c "import duckdb; print(duckdb.__version__)"
1.5.2

$ python3 -c "import duckdb; duckdb.connect().execute(\"LOAD '/app/openrelik/sqlite_scanner.duckdb_extension';\")"
duckdb.duckdb.InvalidInputException: Invalid Input Error: Failed to load
'/app/openrelik/sqlite_scanner.duckdb_extension', The file was built
specifically for DuckDB version 'v1.4.4' and can only be loaded with that
version of DuckDB. (this version of DuckDB is 'v1.5.2')

Impact

Features that rely on the baked extension — in our environment the file-level SQL-query path (/api/v1/files/{file_id}/sql/query) that lets analysts run SQL against uploaded SQLite databases (Plaso SQLite output, app caches, browser history DBs) — fail with the error above until the extension is replaced.

Suggested fix

Two options:

A (minimal): Re-bake the extension at image build time against whatever DuckDB version is in pyproject.toml. A small Dockerfile snippet along these lines fetches the matching version:

RUN python3 -c "import duckdb; c = duckdb.connect(); c.execute('INSTALL sqlite_scanner')" && \
    cp /root/.duckdb/extensions/v*/linux_amd64/sqlite_scanner.duckdb_extension \
       /app/openrelik/sqlite_scanner.duckdb_extension

B (arguably cleaner): Drop the pre-baked file entirely and have the code do INSTALL sqlite_scanner; LOAD sqlite_scanner; on first use. DuckDB will download from extensions.duckdb.org the first time the feature is invoked, cache it under ~/.duckdb/extensions/, and reuse the cached copy on subsequent calls. No version-skew possible. Small cost: first use of the feature in each container incurs a ~3-second network download.

Workaround (in-place fix that we're using today)

docker exec openrelik-server python3 -c "import duckdb; duckdb.connect().execute('INSTALL sqlite_scanner')"
docker exec openrelik-server cp \
  /root/.duckdb/extensions/v1.5.2/linux_amd64/sqlite_scanner.duckdb_extension \
  /app/openrelik/sqlite_scanner.duckdb_extension

Survives container restart; reverts on docker compose pull.

Environment

  • Deployment: CYPFER multi-tenant DFIR platform running OR on isolated per-case Docker containers via docker-compose
  • Image: ghcr.io/openrelik/openrelik-server@sha256:89adb0ebc41f5fbb1296a098c1e440c1761e896aaa0e4be2169dc16eed3a8785
  • Host OS: Ubuntu 22.04 in LXC
  • Reported by: CYPFER-Inc (happy to PR a fix if the team has a preferred approach)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions