FlawOpen

flawopen.com/Referencia/Seguridad de bots de PR

Bots de revisión de PR: controles contra prompt injection y SSRF

Bots de revisión de PR: evita SSRF por prompt injection

Cómo el texto no confiable de una pull request puede influir en herramientas de IA y cómo limitar permisos del bot y acceso a la red.

Riesgo de seguridad CWE-1427 / CWE-918 Seguridad de IA y flujos de desarrollo

ELI5 — Un asistente revisor con acceso a la red privada

Una pull request es como un paquete entregado al equipo revisor: su contenido puede ser útil, pero no se convierte en política de la empresa. Si el revisor de IA también puede consultar URLs arbitrarias desde una red privada, una instrucción engañosa puede influir en el destino. El riesgo depende de los permisos de la herramienta y de la red; leer texto hostil no concede acceso a la red por sí solo.

Conceptos básicos y términos clave

Entrada no confiable:
Títulos, descripciones, comentarios, diffs y enlaces de pull requests de colaboradores.
Prompt injection indirecta:
Texto no confiable influye en el agente porque se incluye en el contexto del modelo.
Límite de SSRF:
Una herramienta de consulta del servidor puede alcanzar destinos a los que el colaborador no llega directamente.
Condiciones de impacto:
También se necesitan un servicio interno accesible, credenciales disponibles y controles insuficientes de autorización o salida de red.

Mecanismo y causa raíz

Un bot revisor puede combinar texto controlado por el colaborador con instrucciones de revisión confiables. El modelo puede proponer una llamada a herramienta basándose en cualquiera de ellos. Los prompts y delimitadores no autorizan el acceso a la red. La SSRF solo es posible si el código acepta un destino elegido por el modelo y una herramienta con acceso a la red puede alcanzarlo. El acceso a metadatos de nube o credenciales es un impacto adicional condicionado, no un resultado automático de la prompt injection.

Ruta de ataque condicionada

1

El colaborador controla contenido de la PR

Un colaborador externo puede influir en títulos, descripciones, comentarios, texto modificado y material enlazado.

2

El agente lee ese contenido

El servicio incluye algunos campos no confiables en el contexto del modelo; esto puede influir en la respuesta o en la propuesta de herramienta.

3

La herramienta determina el alcance

Si el agente puede consultar URLs arbitrarias, el runner puede contactar destinos permitidos por la red. Sin esa herramienta, esta ruta SSRF no existe.

4

El impacto depende del despliegue

Los datos internos o las credenciales solo quedan expuestos si lo permiten los servicios accesibles, la configuración de metadatos, los permisos y los controles de salida.

Código: despacho sin control frente a lectura autorizada

DESPACHO SIMULADO 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/"]
HERRAMIENTA DE LECTURA CON 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)

Lista de controles de ingeniería

Vulnerabilidad documentada relacionada — CVE-2023-32786

El aviso revisado por GitHub para CVE-2023-32786 indica que la prompt injection en LangChain anterior a 0.0.329 podía forzar la consulta de una URL arbitraria (SSRF) e influir en tareas posteriores. El aviso señala 0.0.329 como versión corregida. Es una cadena documentada de consulta de URL; no demuestra un incidente de bot de PR ni robo de metadatos de nube.

Fuentes y orientación principal

Abrir el directorio de seguridad → Ver guías de referencia →
Véase también Falsificación de peticiones del lado del servidor (SSRF, CWE-918): cómo funciona y cómo evitarla en cada lenguaje — flawopen.com SSRF en fetch() de Node.js: cómo obtener URLs con seguridad SSRF y metadatos cloud: riesgos y defensa