FlawOpen

flawopen.com/Referência/Segurança de bots de PR

Bots de revisão de PR: controles contra prompt injection e SSRF

Bots de revisão de PR: evite SSRF por prompt injection

Como texto não confiável de pull requests pode influenciar ferramentas de IA e como limitar permissões do bot e acesso à rede.

Risco de segurança CWE-1427 / CWE-918 Segurança de IA e fluxos de desenvolvimento

ELI5 — Um assistente de revisão com acesso à rede interna

Uma pull request é como um pacote entregue à equipe revisora: o conteúdo pode ser útil, mas não vira política da empresa. Se o revisor de IA também puder buscar URLs arbitrárias dentro da rede privada, uma instrução enganosa poderá influenciar o destino consultado. O risco depende das permissões da ferramenta e da rede; ler texto hostil, por si só, não concede acesso à rede.

Conceitos centrais e termos-chave

Entrada não confiável:
Títulos, descrições, comentários, diffs e links de pull requests enviados por contribuidores.
Prompt injection indireta:
Texto não confiável influencia o agente porque foi incluído no contexto do modelo.
Limite de SSRF:
Uma ferramenta de busca no servidor pode alcançar destinos inacessíveis diretamente ao contribuidor.
Condições de impacto:
Também são necessários um serviço interno acessível, credenciais disponíveis e controles insuficientes de autorização ou saída de rede.

Mecanismo e causa raiz

Um bot de revisão pode combinar texto controlado pelo contribuidor com instruções confiáveis de revisão. O modelo pode propor uma chamada de ferramenta com base em qualquer um deles. Prompts e delimitadores não autorizam acesso à rede. SSRF só é possível quando o código aceita um destino escolhido pelo modelo e uma ferramenta com acesso à rede consegue alcançá-lo. Acesso a metadados de nuvem ou credenciais é um impacto adicional condicionado, não um resultado automático da prompt injection.

Caminho de ataque condicionado

1

O contribuidor controla o conteúdo da PR

Um contribuidor externo pode influenciar títulos, descrições, comentários, texto alterado e materiais vinculados.

2

O agente lê esse conteúdo

O serviço inclui alguns campos não confiáveis no contexto do modelo; isso pode influenciar a resposta ou a proposta de ferramenta.

3

A ferramenta define o alcance

Se o agente puder buscar URLs arbitrárias, o runner poderá contatar destinos permitidos pela rede. Sem essa ferramenta, esse caminho de SSRF não existe.

4

O impacto depende da implantação

Dados internos ou credenciais só ficam expostos se serviços acessíveis, metadados, permissões de identidade e controles de saída permitirem.

Código: despacho sem validação vs. leitura autorizada

DESPACHO DE DEMONSTRAÇÃO INERTE
# INERT DEMO: model-selected URL reaches a mock tool without policy checks
from dataclasses import dataclass

@dataclass
class ToolCall:
    name: str
    arguments: dict[str, str]

class MockFetch:
    def __init__(self):
        self.calls = []

    def __call__(self, url: str) -> str:
        self.calls.append(url)
        return "fixture response"

def dispatch_unchecked(call: ToolCall, tools: dict):
    # The mock records a string; it makes no network request.
    return tools[call.name](**call.arguments)

mock_fetch = MockFetch()
call = ToolCall("fetch_url", {"url": "https://docs.example.invalid/"})
assert dispatch_unchecked(call, {"fetch_url": mock_fetch}) == "fixture response"
assert mock_fetch.calls == ["https://docs.example.invalid/"]
FERRAMENTA DE LEITURA COM POLÍTICA
# SAFE DEMO: the agent receives only a read-only PR capability
from dataclasses import dataclass

@dataclass(frozen=True)
class ReviewContext:
    repository: str
    pull_request: int

@dataclass
class ToolCall:
    name: str
    arguments: dict[str, object]

READ_ONLY_TOOLS = {"read_pr_diff"}

def dispatch_review_call(call: ToolCall, context: ReviewContext, policy, tools):
    if call.name not in READ_ONLY_TOOLS:
        raise PermissionError("Tool is not available to this review")
    expected = {"repository": context.repository,
                "pull_request": context.pull_request}
    if call.arguments != expected:
        raise ValueError("Arguments must match the authorized review")
    if not policy.can_read_pr(context.repository, context.pull_request):
        raise PermissionError("Review principal cannot read this pull request")
    # The injected read_pr_diff function is trusted app code, not model output.
    return tools["read_pr_diff"](**expected)

Checklist de hardening de engenharia

Vulnerabilidade documentada relacionada — CVE-2023-32786

O aviso revisado pelo GitHub para CVE-2023-32786 informa que prompt injection no LangChain anterior a 0.0.329 podia forçar a busca de uma URL arbitrária (SSRF) e influenciar tarefas seguintes. O aviso indica 0.0.329 como corrigido. É uma cadeia documentada de busca por URL; não comprova um incidente de bot de PR nem roubo de metadados de nuvem.

Fontes e orientações principais

Abrir o diretório de segurança → Explorar guias de referência →
Veja também Falsificação de requisição do lado do servidor (SSRF, CWE-918): como funciona e como evitar em todas as linguagens — flawopen.com SSRF no fetch() do Node.js: como buscar URLs com segurança SSRF e metadados de nuvem: riscos e defesas