From a910d70d40903b5cab3c6a8d8680798becfc85f1 Mon Sep 17 00:00:00 2001 From: TPTBusiness Date: Thu, 30 Apr 2026 07:25:14 +0200 Subject: [PATCH] fix(security): whitelist-validate metric column in get_top_factors (B608) The metric parameter was passed directly into an f-string SQL query. Add explicit validation against _ALLOWED_METRICS before use, raising ValueError on unknown values. Raises ValueError on injection attempt instead of silently accepting arbitrary column names. Co-Authored-By: Claude Sonnet 4.6 --- rdagent/components/backtesting/results_db.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/rdagent/components/backtesting/results_db.py b/rdagent/components/backtesting/results_db.py index cf5880b2..3c5105fd 100644 --- a/rdagent/components/backtesting/results_db.py +++ b/rdagent/components/backtesting/results_db.py @@ -190,16 +190,18 @@ class ResultsDatabase: pd.DataFrame DataFrame with factor names and metrics """ - # Map shorthand to full column name + _ALLOWED_METRICS = frozenset({ + 'sharpe', 'ic', 'annual_return', 'max_drawdown', + 'win_rate', 'information_ratio', 'volatility', + }) metric_map = { - 'sharpe': 'sharpe', - 'ic': 'ic', - 'return': 'annual_return', - 'drawdown': 'max_drawdown', - 'win_rate': 'win_rate', + 'sharpe': 'sharpe', 'ic': 'ic', 'return': 'annual_return', + 'drawdown': 'max_drawdown', 'win_rate': 'win_rate', 'information_ratio': 'information_ratio', } col = metric_map.get(metric, metric) + if col not in _ALLOWED_METRICS: + raise ValueError(f"Unknown metric: {metric!r}") return pd.read_sql_query( f"""SELECT factor_name, ic, sharpe, annual_return, max_drawdown, @@ -208,7 +210,7 @@ class ResultsDatabase: JOIN factors ON factor_id = factors.id WHERE {col} IS NOT NULL ORDER BY {col} DESC - LIMIT ?""", + LIMIT ?""", # nosec B608 — col is validated against _ALLOWED_METRICS above self.conn, params=[limit] )