DEV Community

LeoJulieta
LeoJulieta

Posted on

Segurança de Plugins ChatGPT: Detecte e Corrija Vulnerabilidades

Segurança de Plugins do ChatGPT: Guia Prático para Detectar e Mitigar Vulnerabilidades (Jun/24 – Out/26)

Introdução

Desde que a OpenAI abriu o ecossistema de plugins em junho 2024, a segurança dos plugins do ChatGPT virou uma das buscas mais quentes da web. Entre junho 2024 e outubro 2026, o volume de pesquisas por “ChatGPT plugin security” disparou 120 % e, ao mesmo tempo, surgiram relatos de vazamento de credenciais, SSRF e prompt‑injection em comunidades como Hacker News e Reddit.

Se você já integra plugins ao seu produto ou ainda está avaliando a adoção, este artigo entrega um passo‑a‑passo prático, scripts reutilizáveis e pipelines de CI/CD prontos para usar, tudo em português.


Por que isso importa agora

Motivo Dados relevantes
Adoção em massa > 3 200 plugins publicados no marketplace da OpenAI (2024)
Incidentes recentes Out/26: 7 vazamentos de chaves de API, 3 SSRF, 2 prompt‑injection
Regulamentação LGPD & EU‑AI‑SEC exigem controles de segurança documentados
Custo de um breach Gartner: US$ 4,2 mi em média por incidente envolvendo credenciais

A realidade é clara: ignorar a superfície de ataque dos plugins pode custar milhões e colocar sua empresa em risco de sanções regulatórias.


Arquitetura típica de um plugin do ChatGPT

flowchart LR
    U[Usuário (ChatGPT)] <--> G[Gateway OpenAI] <--> B[Backend do Plugin]
    G --> A[Servidor de Autorização (OAuth2)]
    B --> DB[(Banco de Dados/Serviços externos)]
    style U fill:#f9f,stroke:#333,stroke-width:2px
    style G fill:#bbf,stroke:#333,stroke-width:2px
    style B fill:#bfb,stroke:#333,stroke-width:2px
  • Gateway OpenAI: valida o token OAuth 2.0 e encaminha a chamada ao backend.
  • Backend: expõe um endpoint HTTPS (geralmente /openapi.yaml) que o modelo consome.
  • Servidor de Autorização: gera e revoga tokens de acesso.

Pontos críticos: validação de token, controle de CORS, sanitização de parâmetros de entrada e proteção contra chamadas externas não autorizadas (SSRF).


Principais vetores de ataque

Vetor Como funciona Exemplos reais (Out/26)
Prompt Injection Usuário injeta texto que manipula o prompt interno do modelo. Plugin de finanças permitia “…” no campo de descrição, alterando a lógica de cálculo.</td> </tr> <tr> <td><strong>Server‑Side Request Forgery (SSRF)</strong></td> <td>Backend faz requisição a URLs controladas pelo atacante.</td> <td>Plugin de agenda enviava requisição a <code>http://169.254.169.254</code> (metadata AWS).</td> </tr> <tr> <td><strong>Exposição de credenciais</strong></td> <td>Chaves de API armazenadas em variáveis de ambiente sem criptografia.</td> <td>7 plugins vazaram tokens ao logar respostas de depuração.</td> </tr> <tr> <td><strong>Injeção de código</strong></td> <td>Dados não sanitizados são usados em comandos shell ou consultas SQL.</td> <td>Plugin de RH concatenava <code>user_input</code> em um <code>os.system()</code> Python.</td> </tr> </tbody></table> <hr> <h2> <a name="checklist-de-segurança-passo-a-passo" href="#checklist-de-segurança-passo-a-passo" class="anchor"> </a> Checklist de segurança (passo a passo) </h2> <ol> <li><p><strong>Revisão de manifesto</strong> </p> <ul> <li>Verifique <code>openapi.yaml</code> para endpoints expostos.<br></li> <li>Garanta que <code>securitySchemes</code> use <strong>OAuth 2.0</strong> com escopos mínimos.<br></li> </ul></li> <li><p><strong>Hardening do backend</strong> </p> <ul> <li>Habilite <strong>CORS</strong> restrito (<code>https://chat.openai.com</code>).<br></li> <li>Use <strong>HTTPS</strong> com TLS 1.3 e HSTS.<br></li> <li>Desative redirecionamentos externos no servidor HTTP.<br></li> </ul></li> <li><p><strong>Sanitização de entrada</strong> </p> <ul> <li>Empregue bibliotecas como <code>bleach</code> (Python) ou <code>DOMPurify</code> (Node) para limpar HTML/JSON.<br></li> <li>Limite tamanho de payloads (ex.: <code>max_content_length = 1 MiB</code>).<br></li> </ul></li> <li><p><strong>Proteção contra SSRF</strong> </p> <ul> <li>Whitelist de domínios permitidos.<br></li> <li>Bloqueie IPs de rede interna (<code>169.254.0.0/16</code>, <code>10.0.0.0/8</code>).<br></li> </ul></li> <li><p><strong>Gerenciamento de segredos</strong> </p> <ul> <li>Armazene chaves em <strong>Vault</strong>, <strong>AWS Secrets Manager</strong> ou <strong>Azure Key Vault</strong>.<br></li> <li>Rotacione tokens a cada 30 dias.<br></li> </ul></li> <li><p><strong>Monitoramento e logging</strong> </p> <ul> <li>Envie logs de requisição para <strong>Azure Sentinel</strong>, <strong>Splunk</strong> ou <strong>Elastic</strong>.<br></li> <li>Alertas para falhas de autenticação ou chamadas a domínios não whitelist.<br></li> </ul></li> <li><p><strong>Teste automatizado</strong> </p> <ul> <li>Integre scanners de segurança ao pipeline CI/CD (ver tabela comparativa).<br></li> </ul></li> </ol> <hr> <h2> <a name="scripts-úteis" href="#scripts-úteis" class="anchor"> </a> Scripts úteis </h2> <h3> <a name="1-scanner-rápido-de-ssrf-em-python" href="#1-scanner-rápido-de-ssrf-em-python" class="anchor"> </a> 1. Scanner rápido de SSRF em Python </h3> <p></p> <div class="highlight"><pre class="highlight python"><code><span class="kn">import</span> <span class="n">requests</span><span class="p">,</span> <span class="n">json</span><span class="p">,</span> <span class="n">sys</span> <span class="n">TARGET</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="c1"># URL do endpoint do plugin </span><span class="n">PAYLOADS</span> <span class="o">=</span> <span class="p">[</span> <span class="sh">"</span><span class="s">http://169.254.169.254/latest/meta-data/iam/security-credentials/</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">http://127.0.0.1:8000/</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">file:///etc/passwd</span><span class="sh">"</span> <span class="p">]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">PAYLOADS</span><span class="p">:</span> <span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="sh">"</span><span class="s">url</span><span class="sh">"</span><span class="p">:</span> <span class="n">p</span><span class="p">}</span> <span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">post</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="si">{</span><span class="n">TARGET</span><span class="si">}</span><span class="s">/fetch</span><span class="sh">"</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">data</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span> <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">[</span><span class="si">{</span><span class="n">p</span><span class="si">}</span><span class="s">] → </span><span class="si">{</span><span class="n">r</span><span class="p">.</span><span class="n">status_code</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span> </code></pre></div> <p></p> <blockquote> <p><strong>Uso:</strong> <code>python ssrf_scanner.py https://meu-plugin.com/api</code> </p> </blockquote> <h3> <a name="2-verificação-de-chaves-expostas-no-log-bash" href="#2-verificação-de-chaves-expostas-no-log-bash" class="anchor"> </a> 2. Verificação de chaves expostas no log (bash) </h3> <p></p> <div class="highlight"><pre class="highlight shell"><code><span class="c">#!/usr/bin/env bash</span> <span class="nv">logfile</span><span class="o">=</span><span class="nv">$1</span> <span class="nb">grep</span> <span class="nt">-Eo</span> <span class="s1">'sk-[A-Za-z0-9]{48}'</span> <span class="s2">"</span><span class="nv">$logfile</span><span class="s2">"</span> | <span class="nb">sort</span> <span class="nt">-u</span> </code></pre></div> <p></p> <blockquote> <p><strong>Uso:</strong> <code>./check_secrets.sh /var/log/plugin.log</code> </p> </blockquote> <hr> <h2> <a name="integração-cicd-github-actions" href="#integração-cicd-github-actions" class="anchor"> </a> Integração CI/CD (GitHub Actions) </h2> <p></p> <div class="highlight"><pre class="highlight yaml"><code><span class="na">name</span><span class="pi">:</span> <span class="s">Segurança do Plugin</span> <span class="na">on</span><span class="pi">:</span> <span class="na">push</span><span class="pi">:</span> <span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="nv">main</span> <span class="pi">]</span> <span class="na">pull_request</span><span class="pi">:</span> <span class="na">jobs</span><span class="pi">:</span> <span class="na">static-analysis</span><span class="pi">:</span> <span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span> <span class="na">steps</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v4</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Instalar dependências</span> <span class="na">run</span><span class="pi">:</span> <span class="s">pip install -r requirements.txt bandit safety</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Análise de código (Bandit)</span> <span class="na">run</span><span class="pi">:</span> <span class="s">bandit -r .</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Verificar vulnerabilidades de dependências (Safety)</span> <span class="na">run</span><span class="pi">:</span> <span class="s">safety check --full-report</span> <span class="na">ssrf-test</span><span class="pi">:</span> <span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span> <span class="na">needs</span><span class="pi">:</span> <span class="s">static-analysis</span> <span class="na">steps</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v4</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Executar scanner SSRF</span> <span class="na">run</span><span class="pi">:</span> <span class="s">python ssrf_scanner.py https://my-plugin.com/api</span> </code></pre></div> <p></p> <p><em>O pipeline falha automaticamente se o Bandit ou o Safety encontrarem alta severidade.</em> </p> <hr> <h2> <a name="ferramentas-de-auditoria-comparação-rápida" href="#ferramentas-de-auditoria-comparação-rápida" class="anchor"> </a> Ferramentas de auditoria – comparação rápida </h2> <table><thead> <tr> <th>Ferramenta</th> <th>Tipo</th> <th>Integração CI</th> <th>Cobertura</th> <th>Licença</th> </tr> </thead><tbody> <tr> <td><strong>Bandit</strong></td> <td>SAST (Python)</td> <td>GitHub Actions, GitLab CI</td> <td>Injeção, uso de <code>eval</code>, credenciais hard‑coded</td> <td>Apache 2.0</td> </tr> <tr> <td><strong>OWASP ZAP</strong></td> <td>DAST</td> <td>Docker, pipelines</td> <td>SSRF, XSS, autenticação</td> <td>Apache 2.0</td> </tr> <tr> <td><strong>Semgrep</strong></td> <td>SAST + SCA</td> <td>GitHub, Bitbucket</td> <td>Prompt injection, regex</td> <td>GPL‑3</td> </tr> <tr> <td><strong>Trivy</strong></td> <td>SCA + CVE</td> <td>GitHub, GitLab</td> <td>Bibliotecas vulneráveis</td> <td>Apache 2.0</td> </tr> <tr> <td><strong>APIsec</strong></td> <td>API security testing</td> <td>CLI, CI</td> <td>OpenAPI validation, auth flaws</td> <td>Proprietária (trial)</td> </tr> </tbody></table> <hr> <h2> <a name="perguntas-frequentes-faq" href="#perguntas-frequentes-faq" class="anchor"> </a> Perguntas Frequentes (FAQ) </h2> <p><strong>Q1 – Preciso usar OAuth 2.0 obrigatoriamente?</strong><br><br> Sim. O modelo da OpenAI só aceita plugins que exponham um fluxo de autorização OAuth 2.0. Qualquer outro método (API‑Key simples) será rejeitado no marketplace.</p> <p><strong>Q2 – Como detectar prompt injection em tempo real?</strong><br><br> Implemente um middleware que analise o <code>user_message</code> antes de enviá‑lo ao modelo. Exemplo em Node.js:<br> </p> <div class="highlight"><pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">injectionPatterns</span> <span class="o">=</span> <span class="p">[</span><span class="sr">/{{.*}}/</span><span class="p">,</span> <span class="sr">/&lt;script&gt;/i</span><span class="p">];</span> <span class="kd">function</span> <span class="nf">blockInjection</span><span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span> <span class="k">if </span><span class="p">(</span><span class="nx">injectionPatterns</span><span class="p">.</span><span class="nf">some</span><span class="p">(</span><span class="nx">p</span> <span class="o">=&gt;</span> <span class="nx">p</span><span class="p">.</span><span class="nf">test</span><span class="p">(</span><span class="nx">msg</span><span class="p">)))</span> <span class="p">{</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Prompt injection detectada</span><span class="dl">'</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> </code></pre></div> <p></p> <p><strong>Q3 – Qual a frequência ideal para rotacionar tokens?</strong><br><br> Mínimo a cada 30 dias, ou imediatamente após qualquer suspeita de vazamento.</p> <p><strong>Q4 – O que fazer se descobrir um vazamento de chave?</strong> </p> <ol> <li>Revogue o token no</li> </ol> <hr> <p><em>Herramienta mencionada: <a href="https://supabase.com">Supabase</a></em></p>

Top comments (0)