FlawOpen

flawopen.com/Référence/Sécurité des bots de PR

Bots de revue de PR : contrôles contre la prompt injection et la SSRF

Bots de revue de PR : prévenir la SSRF par prompt injection

Comment le texte non fiable d’une pull request peut influencer les outils d’IA, et comment limiter les permissions du bot et l’accès réseau.

Risque de sécurité CWE-1427 / CWE-918 Sécurité de l’IA et des workflows de développement

ELI5 — Un assistant de revue muni d’un accès réseau privé

Une pull request ressemble à un colis remis à l’équipe de revue : son contenu peut être utile, mais ne devient pas une politique de l’entreprise. Si l’assistant IA peut aussi récupérer des URL arbitraires depuis un réseau privé, une instruction trompeuse peut influencer la destination consultée. Le risque dépend des permissions de l’outil et du réseau ; lire un texte hostile ne donne pas à lui seul un accès réseau.

Concepts clés et terminologie

Entrée non fiable :
Titres, descriptions, commentaires, diffs et liens de pull requests envoyés par des contributeurs.
Prompt injection indirecte :
Un texte non fiable influence l’agent parce qu’il est inclus dans le contexte du modèle.
Frontière SSRF :
Un outil de récupération côté serveur peut atteindre des destinations inaccessibles directement au contributeur.
Conditions d’impact :
Il faut aussi un service interne accessible, des identifiants disponibles et des contrôles d’autorisation ou de sortie réseau insuffisants.

Mécanisme et cause racine

Un bot de revue peut combiner du texte contrôlé par le contributeur et des consignes de revue fiables. Le modèle peut proposer un appel d’outil sur la base de l’un ou l’autre. Les prompts et délimiteurs n’autorisent pas l’accès réseau. Une SSRF n’est possible que si le code accepte une destination choisie par le modèle et si l’outil réseau peut l’atteindre. L’accès aux métadonnées cloud ou aux identifiants est un impact conditionnel supplémentaire, pas un résultat automatique de la prompt injection.

Parcours d’attaque conditionnel

1

Le contributeur contrôle le contenu de la PR

Un contributeur externe peut influencer les titres, descriptions, commentaires, textes modifiés et liens.

2

L’agent lit ce contenu

Le service place certains champs non fiables dans le contexte du modèle ; ils peuvent influencer la réponse ou une proposition d’outil.

3

L’outil détermine la portée

Si l’agent peut récupérer des URL arbitraires, le runner peut contacter les destinations autorisées par le réseau. Sans cet outil, cette voie SSRF n’existe pas.

4

L’impact dépend du déploiement

Des données internes ou des identifiants ne sont exposés que si les services accessibles, les paramètres de métadonnées, les permissions d’identité et les contrôles de sortie le permettent.

Code : dispatch sans contrôle et lecture autorisée

DISPATCH SIMULÉ 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/"]
OUTIL DE LECTURE SOUS POLITIQUE
# 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)

Liste de contrôle de durcissement

Vulnérabilité documentée connexe — CVE-2023-32786

L’avis GitHub révisé pour CVE-2023-32786 indique qu’une prompt injection dans LangChain avant 0.0.329 pouvait forcer la récupération d’une URL arbitraire (SSRF) et potentiellement influencer des tâches ultérieures. L’avis indique que la version 0.0.329 corrige le problème. Il s’agit d’une chaîne documentée de récupération d’URL, pas d’un incident de bot de PR ni d’une preuve de vol de métadonnées cloud.

Sources et recommandations principales

Parcourir le répertoire sécurité → Voir les guides de référence →
À voir aussi Falsification de requêtes côté serveur (SSRF, CWE-918) : fonctionnement et prévention dans chaque langage — flawopen.com SSRF avec fetch() Node.js : récupérer des URL sans risque SSRF et métadonnées cloud : risques et défenses