
Analisi dettagliata di CVE-2026-22038, una vulnerabilità ad alta gravità nei blocchi AutoGPT Stagehand che registra le chiavi API in chiaro, inclusi causa principale, impatto e rimedio.
ID CVE: CVE-2026-22038
Prodotto: Piattaforma AutoGPT (integrazione Stagehand)
Versioni interessate: Tutte le versioni fino alla autogpt-platform-beta-v0.6.45 inclusa
Corretto in: autogpt-platform-beta-v0.6.46
Tipo di vulnerabilità: CWE-532 — Inserimento di informazioni sensibili nel file di log
Gravità: Alta
Segnalato da: Panuganti Siva Aditya (@sivaadityacoder)
Data della segnalazione: 19 dicembre 2025
Advisory GitHub: GHSA-rc89-6g7g-v5v7
AutoGPT è una piattaforma open-source che consente agli utenti di creare ed eseguire agenti AI autonomi. Include un'integrazione Stagehand che si collega all'automazione del browser e a provider LLM come OpenAI, Anthropic e Groq.
Durante una revisione del codice dei blocchi Stagehand, ho notato che gli oggetti delle credenziali venivano passati direttamente nelle chiamate logger.info(). Ho tracciato ogni istruzione di log e ho scoperto che veniva chiamato inline — bypassando esplicitamente la protezione fornita da Pydantic.
.get_secret_value()SecretStrIl file vulnerabile:
autogpt_platform/backend/backend/blocks/stagehand/blocks.py
Tre blocchi sono interessati, ciascuno con lo stesso schema:
StagehandObserveBlock (Righe 185–188)
logger.info(f"OBSERVE: Stagehand credentials: {stagehand_credentials}")
logger.info(
f"OBSERVE: Model credentials: {model_credentials} for provider "
f"{model_credentials.provider} secret: {model_credentials.api_key.get_secret_value()}"
)
StagehandActBlock (Righe 285–288)
logger.info(f"ACT: Stagehand credentials: {stagehand_credentials}")
logger.info(
f"ACT: Model credentials: {model_credentials} for provider "
f"{model_credentials.provider} secret: {model_credentials.api_key.get_secret_value()}"
)
StagehandExtractBlock (Righe 373–376)
logger.info(f"EXTRACT: Stagehand credentials: {stagehand_credentials}")
logger.info(
f"EXTRACT: Model credentials: {model_credentials} for provider "
f"{model_credentials.provider} secret: {model_credentials.api_key.get_secret_value()}"
)
Per confermare la sfruttabilità, ho eseguito ogni blocco Stagehand con credenziali valide e ho cercato nei log dell'applicazione:
grep "secret:" /var/log/autogpt/application.log
L'output ha confermato che le chiavi API reali apparivano in chiaro:
[INFO] OBSERVE: Model credentials: ... secret: sk-proj-abc123xyz789...
[INFO] ACT: Model credentials: ... secret: sk-ant-api03-def456uvw...
[INFO] EXTRACT: Model credentials: ... secret: sk-1234567890abcdef...
Il codebase di AutoGPT utilizza correttamente il tipo SecretStr di Pydantic per le chiavi API. Quando un oggetto SecretStr viene incluso in una f-string o stampato normalmente, viene visualizzato come ********** — quella protezione è intenzionale.
La causa principale è che gli sviluppatori hanno chiamato .get_secret_value() direttamente all'interno delle istruzioni logger.info(). Questo estrae esplicitamente il segreto e passa il valore stringa grezzo al logger, bypassando completamente la mascheratura integrata di SecretStr.
Il livello di log è INFO, il che significa che queste istruzioni vengono eseguite negli ambienti di produzione normali — non solo nelle sessioni di debug locale. Ogni volta che uno di questi blocchi viene eseguito con le credenziali, il segreto viene scritto nel file di log.
Scenario di attacco:
secret:, sk-proj- o sk-ant-.curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer sk-proj-abc123xyz789..." \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4", "messages": [{"role": "user", "content": "test"}]}'
Credenziali esposte: chiavi API Stagehand / Browserbase, chiavi API OpenAI, chiavi API Anthropic, chiavi API Groq e qualsiasi credenziale di provider LLM configurata nei blocchi Stagehand.
La patch in autogpt-platform-beta-v0.6.46 rimuove le chiamate .get_secret_value() dalle istruzioni logger.info().
Approccio consigliato — rimuovere completamente il segreto dal log:
# Prima (vulnerabile):
logger.info(
f"OBSERVE: Model credentials: {model_credentials} for provider "
f"{model_credentials.provider} secret: {model_credentials.api_key.get_secret_value()}"
)
# Dopo (corretto):
logger.info(
f"OBSERVE: Model credentials for provider {model_credentials.provider} (API key redacted)"
)
Alternativa — oscuramento, mantenendo intatta la struttura del log:
def redact_secret(value: str) -> str:
if len(value) <= 8:
return "***"
return f"{value[:4]}...{value[-4:]}"
logger.info(
f"OBSERVE: Model credentials for provider {model_credentials.provider} "
f"secret: {redact_secret(model_credentials.api_key.get_secret_value())}"
)
L'approccio di oscuramento espone solo i primi e gli ultimi 4 caratteri — sufficienti per identificare quale chiave è stata utilizzata senza rivelare il segreto completo.
Non chiamare mai .get_secret_value() nelle istruzioni di log. Se il tuo framework ti fornisce un tipo di mascheratura dei segreti (SecretStr, SecretBytes, ecc.), lascia che faccia il suo lavoro. Chiamare il metodo di estrazione all'interno di un logger vanifica l'intero scopo.
INFO è un livello di log di produzione. I dump in stile debug delle credenziali non dovrebbero mai raggiungere INFO. Se hai davvero bisogno di confermare quali credenziali sono attive, registra solo metadati non sensibili (nome del provider, prefisso della chiave, ultimi 4 caratteri).
I file di log sono una superficie di attacco. Trattali come qualsiasi altro archivio di dati sensibili — limita l'accesso, ruotali e verifica cosa viene inserito. Gli strumenti di aggregazione (Splunk, ELK, Datadog) hanno spesso accesso in lettura ampio, quindi un segreto in qualsiasi riga di log è di fatto un segreto anche in quei sistemi.
La correzione è sempre più semplice del bug. Rimuovere due righe di log (o sostituirle con equivalenti oscurati) chiude completamente questa esposizione. Il debito di sicurezza derivante dal "logging di debug temporaneo" lasciato in produzione è comune e prevenibile con la revisione del codice.
Le protezioni SecretStr sono opt-in, non automatiche. Gli sviluppatori devono capire che la protezione vale solo finché nessuno estrae esplicitamente il valore. La revisione del codice dovrebbe segnalare qualsiasi uso di .get_secret_value() al di fuori del percorso di autenticazione.
| Data | Evento |
|---|---|
| 19 dicembre 2025 | Segnalato ai manutentori di AutoGPT tramite Huntr e GitHub Security Advisory |
| 2025–2026 | Il manutentore Nicholas Tindle ha riconosciuto la segnalazione |
| Prima di aprile 2026 | Corretto in autogpt-platform-beta-v0.6.46 |
| 25 aprile 2026 | Assegnato CVE-2026-22038 |