
Laboratório baseado em Docker demonstrando bypass de autenticação CVE-2026-44338 na API Flask legada do PraisonAI. Inclui serviços vulneráveis e corrigidos com script PoC para pesquisa de segurança local.
Laboratório Docker local para CVE-2026-44338, um bypass de autenticação no servidor legado da API Flask do PraisonAI.
Este laboratório demonstra a condição de acesso não autenticado nas rotas legadas da API. Ele utiliza intencionalmente uma reprodução segura ao nível de rota, em vez de uma implantação completa do PraisonAI, para que a prova permaneça focada na falha de autenticação e não dispare fluxos de trabalho reais de agentes ou chamadas externas a LLMs.
CVE-2026-44338 afeta as versões do PraisonAI >= 2.5.6 e <= 4.6.33.
No servidor legado vulnerável da API, a autenticação estava desabilitada por padrão. Como resultado, um chamador não autenticado que conseguisse acessar o servidor da API poderia acessar /agents e acionar a rota de fluxo de trabalho /chat sem um token Bearer.
O problema foi corrigido no PraisonAI 4.6.34 alterando o comportamento padrão para exigir autenticação, a menos que explicitamente desabilitada.
Na versão vulnerável, o servidor legado da API usava padrões de autenticação inseguros:
AUTH_ENABLED = False
AUTH_TOKEN = None
def check_auth():
if not AUTH_ENABLED:
return True
Como check_auth() retornava True quando a autenticação estava desabilitada, as rotas protegidas falhavam abertas.
As rotas afetadas incluíam:
GET /agentsPOST /chatA versão corrigida altera a postura padrão para que a autenticação esteja habilitada, a menos que explicitamente desabilitada através de configuração.
O problema central não era uma primitiva de exploração complexa. Vinha de padrões inseguros no servidor legado da API Flask.
v4.6.33No v4.6.33, a autenticação estava desabilitada por padrão:
AUTH_ENABLED = False
AUTH_TOKEN = None
A verificação de autenticação então falhava aberta:
def check_auth():
if not AUTH_ENABLED:
return True
Isso significa que a requisição era aceita sempre que a autenticação estava desabilitada, mesmo que o chamador não enviasse um cabeçalho Authorization.
O fluxo vulnerável era:
AUTH_ENABLED = False
↓
check_auth() retorna True
↓
GET /agents é permitido
POST /chat é permitido
↓
um chamador não autenticado pode acessar metadados de agentes e alcançar a rota de acionamento do fluxo de trabalho
A parte sensível é que /chat não era apenas um endpoint de status. Ele aceitava uma mensagem do usuário e então chamava o executor de fluxo de trabalho do PraisonAI usando agents.yaml.
v4.6.34No v4.6.34, o comportamento padrão foi alterado para exigir autenticação, a menos que o operador a desabilite explicitamente:
AUTH_ENABLED = os.environ.get("PRAISONAI_API_AUTH", "enabled").strip().lower() != "disabled"
AUTH_TOKEN = os.environ.get("PRAISONAI_API_TOKEN") or None
A versão corrigida também melhora o comportamento de manipulação de tokens:
secrets.compare_digest()127.0.0.1 por padrão, em vez de se expor em todas as interfacesO fluxo corrigido é:
AUTH_ENABLED = True por padrão
↓
a requisição deve incluir um token Bearer válido
↓
token ausente ou inválido retorna 401
↓
/agents e /chat não estão mais acessíveis anonimamente
Este laboratório espelha essa diferença ao nível do código fonte:
vuln -> auth desabilitada por padrão, requisições não autenticadas retornam 200
patched -> auth exigida por padrão, requisições não autenticadas retornam 401
O laboratório contém dois serviços locais:
| Serviço | URL | Comportamento |
|---|---|---|
vuln | http://127.0.0.1:8081 | Reproduz o comportamento vulnerável de falha aberta |
patched | http://127.0.0.1:8082 | Exige autenticação via token Bearer |
Ambos os serviços estão vinculados apenas a 127.0.0.1.
A rota /chat usa um executor fictício em vez de um fluxo de trabalho real do PraisonAI. Isso fornece uma prova observável de que a requisição não autenticada atinge o caminho de acionamento do fluxo de trabalho sem causar efeitos colaterais externos.
.
├── docker-compose.yml
├── vuln
│ ├── Dockerfile
│ └── start_server.py
├── patched
│ ├── Dockerfile
│ └── start_server.py
├── poc
│ └── poc.py
└── .gitignore
└── README.md
docker compose up --build -d
python3 poc/poc.py
O serviço vulnerável permite acesso não autenticado:
=== vuln ===
[unauthenticated] GET /agents
status: 200
[unauthenticated] POST /chat
status: 200
verdict: LIKELY_VULNERABLE
O serviço corrigido bloqueia o acesso não autenticado:
=== patched ===
[unauthenticated] GET /agents
status: 401
[unauthenticated] POST /chat
status: 401
verdict: NOT_VULNERABLE_OR_PROTECTED
Resumo final esperado:
vuln: LIKELY_VULNERABLE
patched: NOT_VULNERABLE_OR_PROTECTED
Verifique a rota vulnerável:
curl -i http://127.0.0.1:8081/agents
Resposta vulnerável esperada:
HTTP/1.1 200 OK
Verifique a rota corrigida:
curl -i http://127.0.0.1:8082/agents
Resposta corrigida esperada:
HTTP/1.1 401 UNAUTHORIZED
Os logs do servidor devem mostrar claramente a diferença:
vuln: "GET /agents HTTP/1.1" 200
patched: "GET /agents HTTP/1.1" 401
docker compose down -v
Este laboratório é destinado apenas a pesquisa de segurança local.
O PoC não:
Aviso do GitHub: GHSA-6rmh-7xcm-cpxj https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-6rmh-7xcm-cpxj
NVD: CVE-2026-44338 https://nvd.nist.gov/vuln/detail/CVE-2026-44338
OSV: GHSA-6rmh-7xcm-cpxj https://osv.dev/vulnerability/GHSA-6rmh-7xcm-cpxj
Código fonte vulnerável: PraisonAI v4.6.33 src/praisonai/api_server.py
https://raw.githubusercontent.com/MervinPraison/PraisonAI/v4.6.33/src/praisonai/api_server.py
Código fonte corrigido: PraisonAI v4.6.34 src/praisonai/api_server.py
https://raw.githubusercontent.com/MervinPraison/PraisonAI/v4.6.34/src/praisonai/api_server.py