Fossil Forum

wmacevoy 1 week, 4 days ago

Post: fossil server on a USE_SEE build never obtains the repo key (saved-key pointer check defeats the prompt)

This was found in an Claude Fable LLM session, but verified as a bug/security problem. I patched my version, but the error is in the fossil code.

On Unix, fossil server repo.efossil on a USE_SEE build fails at startup with SQLITE_NOTADB warnings and "not a valid repository", even though the same repository opens fine with one-shot commands (fossil timeline -R, fossil http) in the same environment. The encryptedrepos doc only notes a server limitation on Windows, so I believe the Unix behavior is unintended.

Mechanism (line refs from 2.29 [7a40eb9748], also present in 2.28):

  1. cmd_webserver calls db_setup_for_saved_encryption_key() before opening the repo. That function pre-allocates a zeroed mlock'd page and points zSavedKey at it, so that request children can later inherit the key (FOSSIL_SEE_PID_KEY / --usepidkey machinery).
  2. First repo open → db_maybe_obtain_encryption_key() does: char zKey = db_get_saved_encryption_key(); if( zKey ){ blob_set(pKey, zKey); } else { / prompt */ } db_get_saved_encryption_key() returns the raw pointer without a validity check, so the zeroed page is mistaken for an already-obtained key. The prompt is skipped, blob_set produces an empty key ("" since p[0]==0), db_maybe_set_encryption_key() then applies nothing (blob_size(&key)>0 is false), and every open fails NOTADB.

The validity predicate already exists (db_have_saved_encryption_key(), which rejects a NULL/empty first byte); it just isn't consulted on this path. Proposed fix:

    --- a/src/db.c
    +++ b/src/db.c
    @@ in db_maybe_obtain_encryption_key
       if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
    -    char *zKey = db_get_saved_encryption_key();
    +    char *zKey = db_have_saved_encryption_key()
    +                   ? db_get_saved_encryption_key() : 0;
         if( zKey ){

With this change the first open obtains the key normally (prompt or other source), and db_set_saved_encryption_key() copies it into the pre-allocated secure page, so forked request children inherit it as the setup function intends. Verified end-to-end: fossil server repo.efossil then serves correctly and remote clients clone/sync against it.

Honest caveat on test setup: I don't have an SEE license, so this was reproduced and verified on a USE_SEE build with SQLCipher substituted as the codec (the pizza-party-vote-fossil project's build). The failing logic is in Fossil's key-handling scaffolding, upstream of any codec, and the same unvalidated pointer check is visible in current trunk — but I'd welcome confirmation from someone with a genuine SEE build. Z 9

drh 1 week, 4 days ago

I don't think there is anyone who supports or uses the USE_SEE compile-time option. If it really does have a security vulnerability, then my preferred solution would be to simply delete all of the USE_SEE logic.

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button