Que fait Sécurité des agents de trading LLM ?
Les agents de trading autonomes ont un modèle de menace plus strict que les applications LLM normales : une injection ou un mauvais chemin d'outil peut directement se transformer en perte d'actifs.
Quand l'utiliser
- Construire un agent IA qui signe et envoie des transactions
- Auditer un bot de trading ou un assistant d'exécution on-chain
- Concevoir la gestion des clés de portefeuille pour un agent
- Donner à un LLM l'accès aux ordres de placement, aux swaps ou aux opérations de trésorerie
Comment ça fonctionne
Superposez les défenses. Aucune vérification unique n'est suffisante. Traitez l'hygiène des prompts, la politique de dépenses, la simulation, les limites d'exécution et l'isolation du portefeuille comme des contrôles indépendants.
Exemples
Traiter l'injection de prompt comme une attaque financière
import re
INJECTION_PATTERNS = [
r'ignore (previous|all) instructions',
r'new (task|directive|instruction)',
r'system prompt',
r'send .{0,50} to 0x[0-9a-fA-F]{40}',
r'transfer .{0,50} to',
r'approve .{0,50} for',
]
def sanitize_onchain_data(text: str) -> str:
for pattern in INJECTION_PATTERNS:
if re.search(pattern, text, re.IGNORECASE):
raise ValueError(f"Potentielle injection de prompt : {text[:100]}")
return text
N'injectez pas aveuglément des noms de jetons, des étiquettes de paires, des webhooks ou des flux sociaux dans un prompt capable d'exécution.
Limites de dépenses strictes
from decimal import Decimal
MAX_SINGLE_TX_USD = Decimal("500")
MAX_DAILY_SPEND_USD = Decimal("2000")
class SpendLimitError(Exception):
pass
class SpendLimitGuard:
def check_and_record(self, usd_amount: Decimal) -> None:
if usd_amount > MAX_SINGLE_TX_USD:
raise SpendLimitError(f"Transaction unique ${usd_amount} dépasse le maximum ${MAX_SINGLE_TX_USD}")
daily = self._get_24h_spend()
if daily + usd_amount > MAX_DAILY_SPEND_USD:
raise SpendLimitError(f"Limite quotidienne : ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}")
self._record_spend(usd_amount)
Simuler avant d'envoyer
class SlippageError(Exception):
pass
async def safe_execute(self, tx: dict, expected_min_out: int | None = None) -> str:
sim_result = await self.w3.eth.call(tx)
if expected_min_out is None:
raise ValueError("min_amount_out est requis avant l'envoi")
actual_out = decode_uint256(sim_result)
if actual_out < expected_min_out:
raise SlippageError(f"Simulation : {actual_out} < {expected_min_out}")
signed = self.account.sign_transaction(tx)
return await self.w3.eth.send_raw_transaction(signed.raw_transaction)
Coupe-circuit
class TradingCircuitBreaker:
MAX_CONSECUTIVE_LOSSES = 3
MAX_HOURLY_LOSS_PCT = 0.05
def check(self, portfolio_value: float) -> None:
if self.consecutive_losses >= self.MAX_CONSECUTIVE_LOSSES:
self.halt("Trop de pertes consécutives")
if self.hour_start_value <= 0:
self.halt("hour_start_value invalide")
return
hourly_pnl = (portfolio_value - self.hour_start_value) / self.hour_start_value
if hourly_pnl < -self.MAX_HOURLY_LOSS_PCT:
self.halt(f"PnL horaire {hourly_pnl:.1%} en dessous du seuil")
Isolation du portefeuille
import os
from eth_account import Account
private_key = os.environ.get("TRADING_WALLET_PRIVATE_KEY")
if not private_key:
raise EnvironmentError("TRADING_WALLET_PRIVATE_KEY non définie")
account = Account.from_key(private_key)
Utilisez un portefeuille chaud dédié avec seulement les fonds de session nécessaires. Ne dirigez jamais l'agent vers un portefeuille de trésorerie principal.
Protection MEV et délai d'expiration
import time
PRIVATE_RPC = "https://rpc.flashbots.net"
MAX_SLIPPAGE_BPS = {"stable": 10, "volatile": 50}
deadline = int(time.time()) + 60
Checklist pré-déploiement
- Les données externes sont désinfectées avant d'entrer dans le contexte LLM
- Les limites de dépenses sont appliquées indépendamment de la sortie du modèle
- Les transactions sont simulées avant l'envoi
min_amount_outest obligatoire- Les coupe-circuits interrompent en cas de perte ou d'état invalide
- Les clés proviennent de variables d'environnement ou d'un gestionnaire de secrets, jamais du code ou des logs
- Un mempool privé ou un routage protégé est utilisé lorsque approprié
- Le glissement et les délais d'expiration sont définis par stratégie
- Toutes les décisions de l'agent sont journalisées dans les logs d'audit, pas seulement les envois réussis