From b5da0df42ad9b4f7525f39e065eee35dcf838098 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 14 Apr 2026 23:23:12 +0200 Subject: [PATCH] Prevent SQLI via dbpath This is reachable only by the admin users, but is still a straightforward RCE vector, if only via SQLite's `ATTACH DATABASE` trick --- cps/db.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cps/db.py b/cps/db.py index 15032026d..74b25c891 100644 --- a/cps/db.py +++ b/cps/db.py @@ -640,8 +640,8 @@ class CalibreDB: connect_args={'check_same_thread': False}, poolclass=StaticPool) with check_engine.begin() as connection: - connection.execute(text("attach database '{}' as calibre;".format(dbpath))) - connection.execute(text("attach database '{}' as app_settings;".format(app_db_path))) + connection.execute(text("attach database '{}' as calibre;".format(dbpath.replace("'", "''")))) + connection.execute(text("attach database '{}' as app_settings;".format(app_db_path.replace("'", "''")))) local_session = scoped_session(sessionmaker()) local_session.configure(bind=connection) database_uuid = local_session().query(Library_Id).one_or_none() @@ -694,8 +694,8 @@ class CalibreDB: poolclass=StaticPool) with engine.begin() as connection: connection.execute(text('PRAGMA cache_size = 10000;')) - connection.execute(text("attach database '{}' as calibre;".format(dbpath))) - connection.execute(text("attach database '{}' as app_settings;".format(app_db_path))) + connection.execute(text("attach database '{}' as calibre;".format(dbpath.replace("'", "''")))) + connection.execute(text("attach database '{}' as app_settings;".format(app_db_path.replace("'", "''")))) conn = engine.connect() # conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302