mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-08-13 04:44:19 +02:00
Escape tokenize argument in enable_fts (#828)
The tokenize value passed to Table.enable_fts() was interpolated directly into the CREATE VIRTUAL TABLE statement inside a single-quoted string literal. A value containing a single quote could break out of that literal and inject arbitrary SQL, which executes via executescript(). This is reachable from the CLI via 'enable-fts --tokenize'. Route the value through the existing Database.quote() helper so SQLite itself escapes it. Legitimate tokenizers such as 'porter' are unaffected. Adds a regression test.
This commit is contained in:
parent
b37b8cf8c8
commit
2d3c6b9a1e
2 changed files with 15 additions and 1 deletions
|
|
@ -3514,7 +3514,9 @@ class Table(Queryable):
|
|||
table_fts=quote_identifier(self.name + "_fts"),
|
||||
columns=", ".join(quote_identifier(c) for c in columns),
|
||||
fts_version=fts_version,
|
||||
tokenize=f"\n tokenize='{tokenize}'," if tokenize else "",
|
||||
tokenize=(
|
||||
f"\n tokenize={self.db.quote(tokenize)}," if tokenize else ""
|
||||
),
|
||||
)
|
||||
)
|
||||
should_recreate = False
|
||||
|
|
|
|||
|
|
@ -252,6 +252,18 @@ def test_fts_tokenize(fresh_db, fts_version):
|
|||
}.items() <= rows[0].items()
|
||||
|
||||
|
||||
def test_fts_tokenize_escaped(fresh_db):
|
||||
# A malicious tokenize value must not be able to break out of the
|
||||
# string literal in the CREATE VIRTUAL TABLE statement.
|
||||
table = fresh_db["searchable"]
|
||||
table.insert_all(search_records)
|
||||
malicious = "porter'); CREATE TABLE injected(x); --"
|
||||
with pytest.raises(Exception):
|
||||
table.enable_fts(["text"], tokenize=malicious)
|
||||
# The injected statement must not have executed
|
||||
assert "injected" not in fresh_db.table_names()
|
||||
|
||||
|
||||
def test_optimize_fts(fresh_db):
|
||||
for fts_version in ("4", "5"):
|
||||
table_name = f"searchable_{fts_version}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue