flawopen.com/Referenz/Sicherheit von PR-Bots
KI-PR-Review-Bots: SSRF durch Prompt Injection verhindern
Wie nicht vertrauenswürdiger Pull-Request-Text KI-Tools beeinflussen kann und wie Bot-Berechtigungen und Netzwerkzugriff begrenzt werden.
ELI5 — Eine Review-Assistenz mit Zugang zum Firmennetz
Ein Pull Request ist wie ein Paket für das Review-Team: Der Inhalt kann nützlich sein, wird dadurch aber nicht zur Unternehmensrichtlinie. Kann die KI-Assistenz beliebige URLs aus einem privaten Netzwerk abrufen, kann eine irreführende Anweisung das Abrufziel beeinflussen. Das Risiko hängt von Tool- und Netzwerkrechten ab; feindlichen Text zu lesen gewährt allein keinen Netzwerkzugriff.
Kernkonzepte und Schlüsselbegriffe
- Nicht vertrauenswürdige Eingaben:
- Titel, Beschreibungen, Kommentare, Diffs und Links aus Pull Requests von Beitragenden.
- Indirekte Prompt Injection:
- Nicht vertrauenswürdiger Text beeinflusst den Agenten, weil er im Modellkontext steht.
- SSRF-Grenze:
- Ein serverseitiges Abruf-Tool kann Ziele erreichen, die Beitragende nicht direkt erreichen.
- Auswirkungsbedingungen:
- Zusätzlich müssen ein interner Dienst erreichbar, Anmeldedaten vorhanden und Autorisierungs- oder Egress-Kontrollen unzureichend sein.
Mechanismus und Ursache
Ein Review-Bot kann von Beitragenden kontrollierten Text mit vertrauenswürdigen Review-Anweisungen kombinieren. Das Modell kann auf Grundlage beider Seiten einen Tool-Aufruf vorschlagen. Prompts und Trennzeichen autorisieren keinen Netzwerkzugriff. SSRF ist nur möglich, wenn Anwendungscode ein vom Modell gewähltes Ziel akzeptiert und ein netzwerkfähiges Tool dieses Ziel erreichen kann. Zugriff auf Cloud-Metadaten oder Anmeldedaten ist eine weitere bedingte Auswirkung, kein automatisches Ergebnis von Prompt Injection.
Bedingter Angriffsablauf
Beitragende kontrollieren PR-Inhalte
Externe Beitragende können Titel, Beschreibungen, Kommentare, geänderte Texte und verlinkte Inhalte beeinflussen.
Der Agent liest diese Inhalte
Der Dienst nimmt bestimmte nicht vertrauenswürdige Felder in den Modellkontext auf; das kann Antwort oder Tool-Vorschlag beeinflussen.
Das Tool bestimmt die Reichweite
Kann der Agent beliebige URLs abrufen, kann der Runner Ziele kontaktieren, die sein Netzwerk zulässt. Ohne dieses Tool gibt es diesen SSRF-Pfad nicht.
Die Auswirkung hängt von der Bereitstellung ab
Interne Daten oder Anmeldedaten sind nur gefährdet, wenn erreichbare Dienste, Metadateneinstellungen, Identitätsrechte und Ausgabekontrollen dies zulassen.
Code: ungeprüfte Weiterleitung und autorisierter Lesezugriff
# 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/"]
# 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)
Checkliste für technische Härtung
- Stellen Sie dieses Szenario nicht als bestätigten PR-Bot-Vorfall dar. Die Seite beschreibt ein bedingtes Designrisiko.
- Verbinden Sie kein beliebiges URL-Abruf-Tool mit einem Reviewer, der nur einen Diff prüfen muss.
- Falls externe Linkvorschauen nötig sind, verwenden Sie einen dedizierten Egress-Dienst mit Ziel-Allowlist, DNS/IP-Prüfung beim Verbindungsaufbau, erneuter Redirect-Prüfung und strikten Zeit- und Größenlimits ohne implizite Zugangsdaten.
- Sperren Sie den Runner für private Netze und Cloud-Metadaten. Deaktivieren Sie Metadaten, wenn der Workload sie nicht benötigt; andernfalls IMDSv2 erzwingen und Hop-Limit für Container prüfen.
- Geben Sie dem Bot eine schreibgeschützte, repositorygebundene Identität. Legen Sie keine Secrets in Jobs für nicht vertrauenswürdige PRs offen und trennen Sie privilegierte Workflows von externem Code.
- Bevorzugen Sie in GitHub Actions für nicht vertrauenswürdigen Code `pull_request` mit minimalen Rechten. Behandeln Sie `pull_request_target` als privilegiert und führen Sie niemals Fork-Code mit dessen Secrets oder Schreib-Token aus.
- Protokollieren Sie abgelehnte Tool-Aufrufe und Zielrichtlinien, aber keine Tokens, vollständigen privaten Diffs oder sensiblen Antwortinhalte.