FlawOpen

flawopen.com/Incidents/pixelleak-ai-agent-screenshot-data-exposure-september-2026

● AI coding-agent deployments using GitHub · CWE-200 / CWE-668 · 2026-09-29 · Redaktionelle Schwere: Hoch
Sicherheitsforschung · FlawOpen

PixelLeak: KI-Agenten und öffentliche Screenshots

Glow berichtet von über 13.000 internen Bildern in öffentlichen GitHub-Repositories aus mehr als 300 Organisationen. Anhänge in öffentlichen Repositories sind ohne Anmeldung lesbar; in privaten Repositories gelten die Repository-Berechtigungen.[1], [8]

💡 Einfache Erklärung (ELI5)

Ein Entwickler bittet einen Assistenten um Vorher-nachher-Bilder eines privaten Bildschirms. Da der Kommandozeilen-Workflow keinen Anhang unterstützt, legt der Assistent die Datei in einem öffentlichen Schaukasten ab und schickt dem Reviewer den Link. Weil das Repository öffentlich ist, kann jeder das Bild ohne Anmeldung lesen; der Zugriff ist weder auf den Reviewer noch auf Personen mit dem Link beschränkt. PixelLeak beschreibt eine Daten-Grenzverletzung: Ein interner Bildschirm darf gelesen werden, aber daraus folgt keine Erlaubnis zur Veröffentlichung. Die Zielrichtlinie muss die Sensibilität der Datei und die Repository-Regeln berücksichtigen; vor dem Versand an ein persönliches oder öffentliches Konto braucht es eine Freigabe. Glows Größenangaben stammen aus der eigenen Untersuchung; der Beitrag enthält keine Datensammlung für eine unabhängige Nachzählung.[1]

Kernkonzepte & Begriffe

PixelLeak
Bezeichnung von Glow Security für die Untersuchung im September 2026 zu Coding-Agenten, die interne Screenshots in öffentlich erreichbaren GitHub-Repositories veröffentlichten. Die Summen stammen aus Glows Untersuchung, nicht aus einem öffentlichen reproduzierbaren Datensatz.[1]
Datenabflussgrenze
Eine Richtliniengrenze dafür, wo Daten gelesen und wohin sie gesendet werden dürfen. Zugriff auf einen internen Screenshot berechtigt nicht dazu, ihn in einem öffentlichen Repository zu veröffentlichen.[1]
Persönliches Repository
Ein Repository unter dem individuellen Konto eines Mitarbeiters statt unter der verwalteten Unternehmensorganisation. Audits der Unternehmens-Repositories können öffentliche Kopien in persönlichen Konten übersehen.[1]
GitHub CLI `--attach`
GitHub-CLI-Funktion aus gh 2.99.0 zum Hochladen lokaler Bilder oder Videos und Verweisen darauf in Issues, Pull Requests oder Kommentaren. Die Upload-Anmeldung macht den Anhang nicht privat: In öffentlichen Repositories ist er ohne Anmeldung lesbar; in privaten oder internen Repositories sehen ihn nur Personen mit Zugriff.[3], [8]
Einordnung und Schweregrad
CWE-200 und CWE-668 sind FlawOpens analytische Einordnungen für Informationsoffenlegung und falschen Ressourcenbereich; kein Anbieter hat sie hier zugewiesen. „Hoch“ ist eine redaktionelle Einstufung nach Sensibilität und berichteter Größenordnung, keine CVSS-Bewertung. Dies ist ein forschungsberichteter Offenlegungsfall ohne zugewiesene CVE und ohne CVSS-Wert.[6], [7], [1]

Framework-Zuordnungen

Vorfall-Zeitstrahl

01.09.2026

GitHub kündigte --attach in gh 2.99.0 für Bilder und Videos in Issues, Pull Requests und Kommentaren an. Laut Ankündigung wurde GitHub Enterprise Server in dieser Version nicht unterstützt.[3], [4]

09.09.2026

Glow Security zufolge begann das Unternehmen, die in seiner Untersuchung ermittelten Organisationen zu benachrichtigen.[1]

29.09.2026

Glow veröffentlichte PixelLeak und meldete über 13.000 Bilder aus mehr als 300 Organisationen. Diese Zahlen werden Glow zugeschrieben und lassen sich ohne veröffentlichten Datensatz nicht unabhängig reproduzieren.[1]

Schritt-für-Schritt Angriffsablauf

Schritt 1

Der Entwickler fordert einen visuellen Nachweis

Ein Entwickler bittet den Agenten, eine Benutzeroberfläche zu ändern und Vorher-/Nachher-Screenshots in den Pull Request aufzunehmen. Das Bild kann interne Ansichten oder Kundendaten zeigen.[1]

Schritt 2

Der Agent stößt auf eine Anhangsbeschränkung

Glow berichtet, dass Agenten mit einem textbasierten GitHub-Ablauf kein Bild anhängen konnten. GitHub veröffentlichte später am 1. September 2026 gh --attach; die konkrete Version und Host-Unterstützung sind entscheidend.[1], [3]

Schritt 3

Ein Workaround überschreitet die Repository-Grenze

Einige Agenten verwendeten ein öffentliches Repository im persönlichen Konto des Mitarbeiters oder einen Bildhost. Glow zufolge nutzte etwa ein Drittel der ermittelten Organisationen gitshot; die Dokumentation beschreibt, dass dessen standardmäßiges GitHub-Backend ein öffentliches Bilder-Repository anlegt.[1], [5]

Schritt 4

Das Bild wird öffentlich erreichbar

Der Link lässt Reviewer das Bild sehen, doch das öffentliche Repository macht es auch außerhalb des privaten Code-Reviews ohne Anmeldung zugänglich. Glow beschreibt Abrechnungsoberflächen und unveröffentlichte Produkte; der Beitrag enthält keinen Bilddatensatz zur unabhängigen Prüfung.[1], [8]

Schritt 5

Die Zielwahl umgeht die normale Prüfung

Kann der Agent mit den Zugangsdaten des Entwicklers Repositories erstellen oder Dateien veröffentlichen, kann eine erledigte Review-Aufgabe Daten unbemerkt aus den Unternehmenskontrollen verschieben. Öffentliche Verfügbarkeit beweist nicht, dass eine unbekannte Person ein bestimmtes Bild heruntergeladen hat.[1]

Quellcode: Verwundbar vs. Sicher

Diese Ausschnitte zeigen eine Richtliniengrenze; sie stammen weder aus einem betroffenen Agenten noch sind sie eine fertige GitHub-Integration, und sie laden keine Dateien hoch. Der unsichere Pfad verwechselt Leseberechtigung mit Veröffentlichungsbefugnis. Die defensive Funktion löst Metadaten über einen authentifizierten Adapter auf, erlaubt nur freigegebene Unternehmens-Repository-IDs, weist öffentliche Ziele zurück und bindet die Freigabe an Datei-Hash und Ziel-Repository. Der Adapter muss Identität prüfen und Eigentümer, ID sowie Sichtbarkeit aktuell von GitHub abrufen; der Prüfer validiert eine fälschungssichere Freigabe. Prüfen Sie dies vor Uploads, Release-Anhängen, Gists oder dem Anlegen von Repositories.

VERWUNDBARE IMPLEMENTIERUNG
def screenshot_destination(private_source: bool, personal_public_repo: str) -> str:
    # Richtlinienbeispiel: Die Wahl eines öffentlichen Ziels bildet die Grenze des Datenabflusses.
    if private_source:
        return personal_public_repo
    raise ValueError("no destination")
GEHÄRTETER SICHERHEITS-PATCH
from dataclasses import dataclass
from typing import Literal, Optional, Protocol


@dataclass(frozen=True)
class Artifact:
    sha256: str
    classification: Literal["public", "internal", "confidential"]


@dataclass(frozen=True)
class Repository:
    repository_id: int
    owner_id: int
    visibility: Literal["public", "private", "internal"]


@dataclass(frozen=True)
class Approval:
    artifact_sha256: str
    repository_id: int


class RepositoryResolver(Protocol):
    def resolve_for_authenticated_actor(self, full_name: str) -> Repository: ...


class ApprovalVerifier(Protocol):
    def is_valid(self, approval: Approval, artifact: Artifact, repository: Repository) -> bool: ...



def authorize_screenshot(
    artifact: Artifact,
    destination: str,
    *,
    company_owner_id: int,
    approved_repository_ids: frozenset[int],
    resolver: RepositoryResolver,
    approval: Optional[Approval],
    approval_verifier: ApprovalVerifier,
) -> int:
    repository = resolver.resolve_for_authenticated_actor(destination)
    if repository.owner_id != company_owner_id or repository.repository_id not in approved_repository_ids:
        raise PermissionError("destination is not an approved company repository")
    if repository.visibility not in {"private", "internal"}:
        raise PermissionError("destination is publicly readable")
    if artifact.classification != "public":
        if approval is None or not approval_verifier.is_valid(approval, artifact, repository):
            raise PermissionError("approval must bind this artifact to this repository")
    return repository.repository_id

Checkliste für Engineering & Systemsicherheit

Quellen