T09 · Insecure Skill Coding Practices
- Location
core/a_share_trader.py:346- Finding
Fail-Open Risk Controls Permit Trading Decisions Based on Synthetic Data
- Content
View full analysis
Vulnerability Details
File Location:
core/a_share_trader.py:346-359, 507-518, 738-784;core/data_interface.py:16-29, 187-219, 273-294;core/real_data_interface.py:137-157, 202-235, 252-289
Vulnerability Type: Fail-open risk management and silent synthetic-data fallback
Risk Level: MediumEvidence
The required production risk-management package is not present in the reviewed project. When it cannot be imported, the engine installs a mock risk manager:
python # 初始化风控管理器 try: from risk_management.core import AShareRiskManager self.risk_manager = AShareRiskManager( max_drawdown=self.config["risk"]["max_drawdown"], stop_loss_per_trade=self.config["risk"]["stop_loss_per_trade"], capital=self.capital, config=self.config ) logger.info("A股风控管理器初始化成功") except ImportError as e: logger.error(f"风控管理器初始化失败: {e}") self.risk_manager = self._create_mock_risk_manager()The fallback manager approves every submitted signal:
python def _create_mock_risk_manager(self): """创建模拟风控管理器""" class MockRiskManager: def __init__(self): pass def check_trade_risk(self, symbol: str, price: float, quantity: int, side: str) -> Tuple[bool, str]: return True, "风险检查通过" return MockRiskManager()A second fail-open path approves signals when no risk manager is available:
python if self.risk_manager: try: approved, reason = self.risk_manager.check_trade_risk(symbol, price, quantity, side) if approved: signal["risk_check"] = {"approved": True, "reason": reason} approved_signals.append(signal) else: signal["risk_check"] = {"approved": False, "reason": reason} logger.warning(f"信号被风控拒绝: {symbol} {side}, 原因: {reason}") except Exception as e: logger.error(f"风控检查失败: {e}") signal["risk_check"] = {"approved": False, "reason": f"风控检查异常: {e}"} else: ...[truncated 6577 chars]- Remediation
View remediation
Remediation Suggestions
-
Fail closed when risk management is unavailable
- Abort initialization in paper and live modes if the production risk manager cannot be imported.
- Allow the mock manager only when an explicit simulation-only setting is enabled.
- Replace unconditional approval with conservative rejection by default.
-
Disable unsupported live execution
- Reject
mode="live"until an authenticated broker adapter, reconciliation process, and production risk manager are configured. - Represent all locally modeled orders as
SIMULATED; never useEXECUTEDwithout confirmation from an external execution venue.
- Reject
-
Add mandatory execution-boundary validation
- Restrict sides to explicitly supported values and ensure
HOLDnever reaches execution. - Validate symbols against an authorized universe.
- Reject non-numeric, non-finite, zero, and negative prices or quantities.
- Enforce exchange lot sizes, available cash, current holdings, maximum positions, position size, industry concentration, daily loss, and drawdown limits.
- Prevent selling more shares than are held.
- Recalculate commissions and exposure using trusted execution prices.
- Restrict sides to explicitly supported values and ensure
-
Make data provenance explicit
- Attach a source, retrieval time, freshness status, and
is_syntheticmarker to every data record. - Prohibit synthetic records from entering paper-with-real-data or live workflows.
- Do not silently replace failed provider responses with random values.
- Return a typed provider error and stop the trading cycle when authoritative data is unavailable.
- Attach a source, retrieval time, freshness status, and
-
Separate interfaces by purpose
- Rename the existing random interface to make its simulation-only role unambiguous.
- Implement real provider adapters separately and require explicit configuration.
- Implement Tushare authentication and retrieval before representing that source as available.
-
Harden deployment and testing
- Add tests proving that missi ...[truncated 399 chars]
-
