Proteggere l'accesso degli agenti agli strumenti
Applichi i principi del privilegio minimo alle autorizzazioni degli strumenti degli agenti, implementi passaggi di conferma prima delle azioni distruttive e verifichi i log delle azioni degli agenti per rilevare comportamenti anomali.
Proteggere l'accesso degli agenti agli strumenti è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Il problema della sicurezza dell'accesso agli strumenti
Quando fornite uno strumento a un agente AI, gli date la possibilità di compiere azioni nel mondo reale. Uno strumento che invia email, esegue query SQL, chiama API di pagamento o modifica file può causare danni ingenti se l'agente viene compromesso da un attacco di prompt injection o commette semplicemente un errore. Proteggere l'accesso degli agenti agli strumenti significa progettare il livello degli strumenti in modo che i danni derivanti da ogni singolo utilizzo siano limitati, verificabili e reversibili quando possibile.
Il principio del privilegio minimo
Applicate il principio del privilegio minimo a ogni strumento: assegnate all'agente l'accesso minimo necessario per completare l'attività assegnata, e nulla di più. Se l'agente deve leggere i dati dei clienti, fornitegli una connessione di sola lettura al database, non la connessione completa da amministratore che usate per la manutenzione. Se invia notifiche, limitate la sua chiave API al solo endpoint delle notifiche. Il privilegio minimo limita l'entità dei danni di qualsiasi incidente di sicurezza.
from enum import Enum
from dataclasses import dataclass
class Permission(Enum):
READ_CUSTOMER_PROFILE = 'read_customer_profile'
SEND_NOTIFICATION = 'send_notification'
READ_ORDER_HISTORY = 'read_order_history'
WRITE_CUSTOMER_PROFILE = 'write_customer_profile' # higher privilege
PROCESS_REFUND = 'process_refund' # highest risk
@dataclass
class AgentIdentity:
agent_id: str
allowed_permissions: set[Permission]
# Support chat agent: read-only + send notification only
SUPPORT_AGENT = AgentIdentity(
agent_id='support-agent-v1',
allowed_permissions={
Permission.READ_CUSTOMER_PROFILE,
Permission.READ_ORDER_HISTORY,
Permission.SEND_NOTIFICATION # can notify, but NOT write or refund
}
)
# NOT: give every agent all permissions for convenienceEsecuzione degli strumenti con controllo delle autorizzazioni
Applicate il privilegio minimo a livello di esecuzione, non solo a livello di progettazione. Ogni chiamata a uno strumento deve passare attraverso un controllo delle autorizzazioni che verifichi che l'agente chiamante disponga dell'autorizzazione richiesta per quella specifica azione. Questo controllo non può essere aggirato dall'agente né da un attacco di prompt injection, perché viene applicato nel codice e non nel prompt dell'LLM.
class ToolGateway:
def __init__(self, agent: AgentIdentity):
self.agent = agent
self.audit_log = []
def execute_tool(self, tool_name: str, required_permission: Permission, tool_fn, **kwargs) -> dict:
# Permission check - enforced in code, not in the LLM prompt
if required_permission not in self.agent.allowed_permissions:
self.log_denied(tool_name, required_permission, kwargs)
raise PermissionError(
f'Agent {self.agent.agent_id} does not have permission: {required_permission.value}'
)
# Execute tool
result = tool_fn(**kwargs)
self.log_allowed(tool_name, kwargs, result)
return result
def log_denied(self, tool: str, permission: Permission, args: dict):
entry = {'type': 'DENIED', 'agent': self.agent.agent_id, 'tool': tool, 'permission': permission.value, 'args': args}
self.audit_log.append(entry)
print(f'SECURITY: Permission denied - {entry}')
def log_allowed(self, tool: str, args: dict, result):
entry = {'type': 'ALLOWED', 'agent': self.agent.agent_id, 'tool': tool, 'args': args}
self.audit_log.append(entry)
gateway = ToolGateway(SUPPORT_AGENT)
# This will succeed (agent has READ permission)
gateway.execute_tool('read_profile', Permission.READ_CUSTOMER_PROFILE, read_customer_profile, user_id='123')
# This will raise PermissionError (agent lacks PROCESS_REFUND permission)
gateway.execute_tool('process_refund', Permission.PROCESS_REFUND, process_refund, order_id='456', amount=50.00)Passaggi di conferma per le azioni distruttive
Alcune azioni sono irreversibili o hanno un impatto elevato: eliminare record, inviare email in massa, elaborare transazioni finanziarie. Richiedete una conferma esplicita da parte di una persona prima che l'agente esegua una di queste azioni. L'agente propone l'azione, indicando cosa vuole fare e perché; una persona la approva o la rifiuta; solo a quel punto l'esecuzione può procedere. Questo controllo di conferma è la difesa singola più efficace contro gli errori degli agenti e gli abusi derivanti da injection.
HIGH_RISK_ACTIONS = {
'delete_customer_record',
'send_bulk_email',
'process_refund_over_100',
'deploy_code',
'revoke_user_access'
}
def execute_with_confirmation(tool_name: str, tool_args: dict, agent_reasoning: str) -> dict:
if tool_name in HIGH_RISK_ACTIONS:
# Pause and request human approval
approval_request = {
'action': tool_name,
'arguments': tool_args,
'agent_reasoning': agent_reasoning,
'risk_level': 'HIGH'
}
approval = request_human_approval(approval_request) # blocks until human responds
if not approval.approved:
return {'status': 'rejected', 'reason': approval.rejection_reason}
# Log the approval for audit trail
log_approval(tool_name, tool_args, approved_by=approval.approver_id)
# Execute only after confirmation
return execute_tool(tool_name, **tool_args)Limitare gli strumenti: tempo, utenti e dati
Oltre ai tipi di autorizzazione, limitate l'accesso agli strumenti lungo tre dimensioni. Limiti temporali: chiavi API o token che scadono al termine della sessione dell'agente. Limiti per utente: un agente che assiste l'utente A non deve mai accedere ai dati dell'utente B, anche se gli viene ordinato di farlo. Limiti sui dati: un agente del supporto clienti deve accedere solo ai dati del cliente che sta assistendo in quel momento, non a quelli di tutti i clienti. Implementate questi limiti nelle implementazioni degli strumenti, non nei prompt degli agenti.
class ScopedCustomerTool:
def __init__(self, current_user_id: str, session_token: str):
self.user_id = current_user_id # agent can only access THIS user's data
self.token = session_token # expires at end of session
def get_customer_profile(self) -> dict:
# Hardcoded to current user - agent cannot change this via prompt
return db.query(
'SELECT * FROM customers WHERE id = %s',
(self.user_id,) # parameterized, always this user's ID only
)
def get_order_history(self, limit: int = 10) -> list:
# Even if the agent says 'get orders for user 999', it gets self.user_id
return db.query(
'SELECT * FROM orders WHERE customer_id = %s ORDER BY date DESC LIMIT %s',
(self.user_id, min(limit, 50)) # cap limit too
)
# Inject scoped tool into agent - cannot be overridden by prompt
def create_support_agent(user_id: str, session_token: str):
scoped_tools = ScopedCustomerTool(user_id, session_token)
return AgentExecutor(llm=llm, tools=[scoped_tools.get_customer_profile, scoped_tools.get_order_history])Convalida degli input degli argomenti degli strumenti
Gli agenti generano gli argomenti degli strumenti sotto forma di testo. Prima di eseguire qualsiasi strumento, convalidate tutti gli argomenti rispetto a uno schema rigoroso. Questo previene: l'SQL injection tramite i parametri degli strumenti, gli attacchi di path traversal (l'agente che passa '../../../etc/passwd' come percorso di un file), gli attacchi SSRF (l'agente che passa l'URL di un servizio interno come parametro 'remote URL') e l'overflow degli interi o i valori fuori intervallo che potrebbero causare comportamenti imprevisti.
from pydantic import BaseModel, validator, constr, confloat
import re
class SendEmailArgs(BaseModel):
to: str
subject: constr(max_length=200)
body: constr(max_length=10000)
@validator('to')
def must_be_company_email(cls, v):
if not re.match(r'^[^@]+@(?:yourcorp\.com|partner\.com)$', v):
raise ValueError('Email must be sent to yourcorp.com or partner.com domains only')
return v
class ReadFileArgs(BaseModel):
filename: constr(pattern=r'^[a-zA-Z0-9_\-\.]+$') # alphanumeric only, no path traversal
@validator('filename')
def no_parent_directory(cls, v):
if '..' in v or '/' in v or '\\' in v:
raise ValueError('Path traversal detected')
return v
# Validate before execution
def validated_send_email(args_dict: dict) -> dict:
args = SendEmailArgs(**args_dict) # raises ValueError on invalid input
return send_email(args.to, args.subject, args.body)Logging di audit immutabile
Ogni chiamata a uno strumento effettuata da un agente deve essere registrata in un log di audit immutabile. La voce di log deve includere: l'ID dell'agente e l'ID della sessione, il nome dello strumento e tutti gli argomenti, il valore restituito, il timestamp e il ragionamento dichiarato dall'agente per effettuare la chiamata. Immutabile significa che l'agente, o un attaccante, non può eliminare o modificare le voci di log. Usate uno storage append-only, come i servizi di logging cloud, i database write-once o lo storage WORM.
import hashlib
import json
import time
class ImmutableAuditLog:
def __init__(self, log_backend):
self.backend = log_backend # e.g., CloudWatch, BigQuery, or append-only file
self.previous_hash = '0' * 64 # genesis hash
def record(self, agent_id: str, tool_name: str, args: dict, result, reasoning: str):
entry = {
'agent_id': agent_id,
'tool': tool_name,
'args': args,
'result_summary': str(result)[:500], # truncate large results
'reasoning': reasoning[:1000],
'timestamp': time.time(),
'previous_hash': self.previous_hash # chain entries like a blockchain
}
entry_json = json.dumps(entry, sort_keys=True)
entry['hash'] = hashlib.sha256(entry_json.encode()).hexdigest()
self.backend.append(entry) # append-only, never update
self.previous_hash = entry['hash']
return entry['hash']Rilevamento dei comportamenti anomali degli agenti
Anche in presenza di controlli delle autorizzazioni e log di audit, monitorate i pattern di comportamento anomalo che indicano che un agente potrebbe essere stato compromesso o si comporta in modo imprevisto. Tra i segnali di anomalia figurano: un agente di supporto che improvvisamente chiama strumenti mai utilizzati prima, un aumento insolito nella frequenza delle chiamate agli strumenti da parte di un agente, argomenti che differiscono dalla norma in modi sospetti, come stringhe insolitamente lunghe o sequenze di caratteri insolite, oppure chiamate effettuate in orari inconsueti.
from collections import Counter
class AgentBehaviorMonitor:
def __init__(self):
self.tool_call_counts = Counter() # tracks historical tool usage
self.arg_length_history = {} # tracks typical argument lengths
def record_and_check(self, agent_id: str, tool_name: str, args: dict) -> list[str]:
key = f'{agent_id}:{tool_name}'
anomalies = []
self.tool_call_counts[key] += 1
# Flag tools never called before by this agent
if self.tool_call_counts[key] == 1 and tool_name not in COMMON_TOOLS:
anomalies.append(f'First time agent {agent_id} called unusual tool: {tool_name}')
# Flag unusually long arguments (potential injection payload)
total_arg_length = sum(len(str(v)) for v in args.values())
if tool_name not in self.arg_length_history:
self.arg_length_history[tool_name] = []
self.arg_length_history[tool_name].append(total_arg_length)
if len(self.arg_length_history[tool_name]) > 10:
avg = sum(self.arg_length_history[tool_name]) / len(self.arg_length_history[tool_name])
if total_arg_length > avg * 5:
anomalies.append(f'Unusually long arguments for {tool_name}: {total_arg_length} chars (avg: {avg:.0f})')
return anomaliesScadenza dei token e limitazione delle sessioni
Le sessioni degli agenti devono avere una durata definita. Rilasciate all'agente token o credenziali di breve durata all'avvio della sessione e revocateli al termine della sessione. Se la sessione di un agente viene compromessa durante l'esecuzione, la capacità dell'attaccante di sfruttarla è limitata dalla scadenza del token. La limitazione delle sessioni garantisce inoltre che un singolo agente compromesso non possa essere utilizzato per attacchi successivi a distanza di giorni.
import secrets
import time
class SessionTokenManager:
def __init__(self, ttl_seconds=3600):
self.tokens = {} # token -> (agent_id, user_id, expires_at)
self.ttl = ttl_seconds
def issue_token(self, agent_id: str, user_id: str) -> str:
token = secrets.token_urlsafe(32)
expires_at = time.time() + self.ttl
self.tokens[token] = (agent_id, user_id, expires_at)
return token
def validate_token(self, token: str) -> dict | None:
if token not in self.tokens:
return None
agent_id, user_id, expires_at = self.tokens[token]
if time.time() > expires_at:
del self.tokens[token] # clean up expired token
return None
return {'agent_id': agent_id, 'user_id': user_id}
def revoke_token(self, token: str):
self.tokens.pop(token, None)
token_manager = SessionTokenManager(ttl_seconds=1800) # 30-minute sessionsTest della sicurezza degli strumenti
Testate il livello di sicurezza degli strumenti simulando attacchi: provate a chiamare uno strumento limitato con un agente non autorizzato, fornite argomenti con path traversal, inserite stringhe di istruzioni nei parametri degli strumenti e tentate di chiamare strumenti con token scaduti. Una suite completa di test per la sicurezza degli strumenti deve coprire tutti i limiti delle autorizzazioni, tutte le regole di convalida e tutti i trigger di rilevamento delle anomalie.
Progettare la reversibilità
Quando possibile, progettate strumenti reversibili o con esecuzione a fasi. Invece di eliminare immediatamente un record, contrassegnatelo come eliminato con un tombstone, in modo da poterlo ripristinare. Invece di inviare subito un'email, inseritela in una coda 'pending send' che venga elaborata dopo una finestra di revisione di 5 minuti. Sottoponete le transazioni finanziarie a un blocco temporaneo prima del regolamento. La reversibilità non elimina il rischio per la sicurezza, ma riduce drasticamente l'impatto degli attacchi riusciti.
Verifica rapida
Verificate la vostra comprensione della protezione dell'accesso degli agenti agli strumenti trattata in questa lezione.
Riepilogo della lezione
In questa lezione avete imparato che il principio del privilegio minimo limita le autorizzazioni degli strumenti a ciò di cui ogni ruolo dell'agente ha effettivamente bisogno; i controlli delle autorizzazioni a livello di codice applicano queste autorizzazioni in modo da non poter essere aggirate tramite prompt injection; e i passaggi di conferma da parte di una persona per le azioni ad alto rischio forniscono un'ultima rete di sicurezza prima dell'esecuzione di operazioni irreversibili. Ora passeremo a un esercizio strutturato di red teaming sulle applicazioni LLM.
Domande Frequenti
La lezione «Proteggere l'accesso degli agenti agli strumenti» è gratuita?
Sì — il testo completo di «Proteggere l'accesso degli agenti agli strumenti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Proteggere l'accesso degli agenti agli strumenti»?
Applichi i principi del privilegio minimo alle autorizzazioni degli strumenti degli agenti, implementi passaggi di conferma prima delle azioni distruttive e verifichi i log delle azioni degli agenti… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Proteggere l'accesso degli agenti agli strumenti»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Tassonomia degli attacchi di prompt injection
- Difendersi dall'injection nei sistemi RAG
- Proteggere l'accesso degli agenti agli strumenti
- Eseguire un red team sulla propria applicazione LLM