Skip to content

Fail fast extensions#20605

Merged
lnkuiper merged 15 commits into
duckdb:v1.4-andiumfrom
carlopi:fail_fast_extensions
Jan 22, 2026
Merged

Fail fast extensions#20605
lnkuiper merged 15 commits into
duckdb:v1.4-andiumfrom
carlopi:fail_fast_extensions

Conversation

@carlopi
Copy link
Copy Markdown
Member

@carlopi carlopi commented Jan 20, 2026

Changes so that INSTALL also performs signature checks (according to database configuration).
This is somewhat redundant, BUT avoids cases where one might successful install an extension that can't be then loaded.

Logic is as follows:

  1. files ending in ".duckdb_extension" can only be created in the INSTALL path
  2. when moving, either ending ".duckdb_extension" is present both in source and target, OR it should not be present on target
  3. on install, we first verify signature of the buffer, then copy data to "name.tmp-UUID.duckdb_extension", then move it to "name.duckdb_extension". Note that this is legal with both 1 & 2, and makes so that all files (written by duckdb) that ends in '.duckdb_extension' are signature checked
  4. on load, we load only from files eneding in ".duckdb_extension"

Basically there are 3 families of files:

  • A: those ending in '.duckdb_extension'
  • B. the other files

B can be created and moved into freely
A can only be created during install path (since it's the only place where we pass the flag, and we will only create B)
A can only be moved into from other A files, while A can be moved to a B
A is the only type of file we would load from

… or moved in default situations

For creations, opening a file for writing is forbidden if the relevant flag is missing
For moveing A into B, either B is NOT an extension, or both A AND B are extensions

Note that this means temporary files are also named ending in '.duckdb_extension'
… extensions are enabled)

This enforces that extensions are only loaded if ending in '.duckdb_extension'
For development reasons, LOAD <path> is still possible when extension signature checks are disabled
@carlopi carlopi marked this pull request as draft January 20, 2026 11:17
@carlopi carlopi force-pushed the fail_fast_extensions branch from b8eb198 to 03ae81a Compare January 20, 2026 11:20
@carlopi carlopi marked this pull request as ready for review January 20, 2026 11:20
Copy link
Copy Markdown
Member

@samansmink samansmink left a comment

Choose a reason for hiding this comment

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

Looks great! left a few comments

Comment thread src/include/duckdb/common/opener_file_system.hpp Outdated
Comment thread src/include/duckdb/common/opener_file_system.hpp Outdated
Comment thread src/main/extension/extension_install.cpp Outdated
Comment thread src/main/extension/extension_load.cpp Outdated
Copy link
Copy Markdown
Collaborator

@Mytherin Mytherin left a comment

Choose a reason for hiding this comment

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

Looks good - some comments from my side

target_file->Close();
target_file.reset();
fs.TryRemoveFile(path);
throw IOException("Attempting to install an extension file that hasn't a valid signature, see "
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe use the error manager here similar to what we do for ErrorType::UNSIGNED_EXTENSION so we can override suggestions for it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, that would be cleaner, but I opted NOT to add them, given this will require changes client side for a patch release.
This can be considered for v1.5.0.

Comment thread src/include/duckdb/common/opener_file_system.hpp Outdated
Comment thread src/common/file_system.cpp Outdated
Comment thread src/main/extension/extension_install.cpp Outdated
Comment thread src/include/duckdb/common/opener_file_system.hpp Outdated
VerifyCanAccessFile(source);
VerifyCanAccessFile(target);
if (StringUtil::EndsWith(target, "duckdb_extension") && !StringUtil::EndsWith(source, "duckdb_extension")) {
throw PermissionException("File '%s' cannot be moved to '%s' due to the suffix 'duckdb_extension'", source,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

On that note - we should only check this if allow_unsigned_extensions is enabled.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It would also be nicer if this was pushed into VerifyCanAccessFile somehow - e.g. by pushing in the action:

VerifyCanAccessFile(source, FileOperationType::MOVE_FILE)

Copy link
Copy Markdown
Member Author

@carlopi carlopi Jan 21, 2026

Choose a reason for hiding this comment

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

On that note - we should only check this if allow_unsigned_extensions is enabled.

I opted here to implement this independently from allow_unsigned_extensions flag, basically duckdb will never write to files ending in allow_unsigned_extensions, and never move them (but if both are extensions), and signature checks are independent and performed on LOAD or now INSTALL (and those will have the check on allow_unsigned_extensions or whether community extensions are enabled or not.

Comment thread src/main/extension/extension_install.cpp Outdated
@carlopi carlopi marked this pull request as draft January 20, 2026 12:56
@carlopi carlopi force-pushed the fail_fast_extensions branch 2 times, most recently from 5586e21 to e30ba53 Compare January 20, 2026 15:04
@carlopi carlopi force-pushed the fail_fast_extensions branch from e30ba53 to 3791a27 Compare January 20, 2026 19:36
@carlopi carlopi marked this pull request as ready for review January 21, 2026 08:42
@carlopi
Copy link
Copy Markdown
Member Author

carlopi commented Jan 21, 2026

There are still two comments not properly handled.

@duckdb-draftbot duckdb-draftbot marked this pull request as draft January 21, 2026 10:16
@carlopi carlopi marked this pull request as ready for review January 21, 2026 10:16
@carlopi carlopi force-pushed the fail_fast_extensions branch from b826c86 to 3abba50 Compare January 21, 2026 10:21
@duckdb-draftbot duckdb-draftbot marked this pull request as draft January 21, 2026 10:21
@carlopi carlopi force-pushed the fail_fast_extensions branch from 3abba50 to 9ab4b88 Compare January 21, 2026 10:22
@carlopi carlopi marked this pull request as ready for review January 21, 2026 10:22
@carlopi carlopi requested a review from samansmink January 21, 2026 10:25
@carlopi carlopi mentioned this pull request Jan 21, 2026
@carlopi carlopi marked this pull request as draft January 21, 2026 14:06
@carlopi carlopi force-pushed the fail_fast_extensions branch from 1347c9d to d5dcf30 Compare January 21, 2026 14:06
@carlopi carlopi marked this pull request as ready for review January 21, 2026 14:06
@carlopi carlopi marked this pull request as draft January 21, 2026 14:20
@carlopi carlopi force-pushed the fail_fast_extensions branch from d5dcf30 to c195649 Compare January 21, 2026 14:20
@carlopi carlopi marked this pull request as ready for review January 21, 2026 14:21
Comment thread src/include/duckdb/common/file_open_flags.hpp Outdated
Comment thread src/main/extension/extension_install.cpp Outdated
Comment thread src/main/extension/extension_install.cpp Outdated
Comment thread src/main/extension/extension_install.cpp Outdated
Comment thread src/main/extension/extension_load.cpp Outdated
…uffer (already in memory)

Use those to check for signature validity BEFORE writing temporary extension file to disk
@carlopi carlopi force-pushed the fail_fast_extensions branch 2 times, most recently from 837b514 to f0b38e6 Compare January 21, 2026 15:34
@duckdb-draftbot duckdb-draftbot marked this pull request as draft January 21, 2026 16:17
@carlopi carlopi marked this pull request as ready for review January 21, 2026 16:28
@carlopi carlopi force-pushed the fail_fast_extensions branch from 55eaf54 to 1668d9a Compare January 21, 2026 16:48
@duckdb-draftbot duckdb-draftbot marked this pull request as draft January 21, 2026 16:50
@carlopi carlopi marked this pull request as ready for review January 21, 2026 17:05
@carlopi carlopi marked this pull request as draft January 21, 2026 17:14
@carlopi carlopi force-pushed the fail_fast_extensions branch from 1668d9a to 79b498b Compare January 21, 2026 20:13
@carlopi carlopi marked this pull request as ready for review January 21, 2026 20:13
@carlopi carlopi requested a review from samansmink January 22, 2026 08:29
@lnkuiper lnkuiper merged commit 6ddac80 into duckdb:v1.4-andium Jan 22, 2026
61 checks passed
github-actions Bot pushed a commit to duckdb/duckdb-r that referenced this pull request Jan 22, 2026
github-actions Bot added a commit to duckdb/duckdb-r that referenced this pull request Jan 22, 2026
Fail fast extensions (duckdb/duckdb#20605)

Co-authored-by: krlmlr <krlmlr@users.noreply.github.com>
Mytherin added a commit that referenced this pull request Feb 2, 2026
Tested on fork's CI to be working, according to changes that landed in
#20605.

Should make so nightly CI for `v1.4-varieagata` (and later other brances
as well) should pass for "Extension updating test".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants