Summary
The GHSA-x46r fix (commit 39161f0) addressed SQL injection in the TimescaleDB export module by converting all SQL operations to use parameterized queries and psycopg.sql composable objects. However, the DuckDB export module (glances/exports/glances_duckdb/__init__.py) was not included in this fix and contains the same class of vulnerability: table names and column names derived from monitoring statistics are directly interpolated into SQL statements via f-strings. While DuckDB INSERT values already use parameterized queries (? placeholders), the DDL construction and table name references do not escape or parameterize identifier names.
Details
The DuckDB export module constructs SQL DDL statements by directly interpolating stat field names and plugin names into f-strings.
Vulnerable CREATE TABLE construction (glances/exports/glances_duckdb/__init__.py:156-162):
create_query = f"""
CREATE TABLE {plugin} (
{', '.join(creation_list)}
);"""
self.client.execute(create_query)
The creation_list is built from stat dictionary keys in the update() method (glances/exports/glances_duckdb/__init__.py:117-118):
for key, value in plugin_stats.items():
creation_list.append(f"{key} {convert_types[type(self.normalize(value)).__name__]}")
The INSERT statement also uses the unescaped plugin name (glances/exports/glances_duckdb/__init__.py:172-174):
insert_query = f"""
INSERT INTO {plugin} VALUES (
{', '.join(['?' for _ in values])}
);"""
While INSERT values use ? placeholders (safe), the table name {plugin} is directly interpolated in both CREATE TABLE and INSERT INTO statements. Column names in creation_list are also directly interpolated without quoting.
Comparison with the TimescaleDB fix (commit 39161f0):
The TimescaleDB fix addressed this exact pattern by: