Przejdź do treści
DedicatedPHP Kontakt

Dokumenty, które próbują wydawać instrukcje: jak ograniczyć prompt injection w aplikacji PHP

Dowiedz się, jak traktować pobrane dokumenty jako niezaufane dane, ograniczać narzędzia i uprawnienia, walidować odpowiedzi oraz testować integrację AI w PHP.

Diagram aplikacji PHP oddzielającej niezaufane dokumenty, kontrolę dostępu i walidację odpowiedzi AI

Funkcja odpowiadająca na pytania dotyczące dokumentów może pobrać odpowiedni tekst i przekazać go modelowi AI. Taki tekst nie zawsze jest jednak nieszkodliwy: dokument, strona internetowa lub plik dostarczony przez użytkownika może zawierać sformułowania mające zmienić zadanie, uzyskać cudze informacje lub wywołać określone działanie. To ryzyko nazywa się prompt injection w dokumentach lub pośrednią iniekcją promptu, ponieważ instrukcje trafiają do systemu w przetwarzanej treści, a niekoniecznie w pytaniu użytkownika.

Ograniczanie tego ryzyka nie polega na znalezieniu idealnego sformułowania wiadomości systemowej. Chodzi o takie zaprojektowanie aplikacji, by pobrana treść nie mogła zmieniać uprawnień, zasad ani decyzji biznesowych, a odpowiedź modelu nigdy nie stanowiła wystarczającego upoważnienia do działania.

Jakie ryzyko należy kontrolować

Jakie ryzyko należy kontrolować — guía visual de DedicatedPHP

Dokument może zawierać jawne instrukcje, takie jak „zignoruj poprzednie instrukcje”, albo bardziej podstępny tekst, na przykład prośbę o ujawnienie danych wewnętrznych. Może też zawierać ukryte instrukcje w treści wyodrębnionej z HTML, komentarzach, metadanych lub tekście wygenerowanym przez OCR. Jeśli takie materiały zostaną bez rozróżnienia połączone z instrukcjami aplikacji, model może wykonać część z nich, przedstawić stronnicze podsumowanie lub wygenerować nieprzewidzianą odpowiedź.

Ryzyko zależy od tego, co może zrobić dana funkcja. Asystent, który jedynie przygotowuje odpowiedź do sprawdzenia, ma inny wpływ niż taki, który może przeglądać konta, przyznawać zwroty lub wysyłać wiadomości. Zanim funkcja zostanie udostępniona użytkownikom, należy określić, jakie informacje może otrzymywać, jakie odpowiedzi może generować i jakie konsekwencje mogą z nich wynikać.

Sam prompt injection nie dowodzi, że doszło do naruszenia kontroli dostępu w aplikacji. Może jednak ujawnić informacje nieprawidłowo umieszczone w kontekście albo skłonić model do zażądania wykonania operacji. Zabezpieczenia muszą obejmować zarówno dane wejściowe i dostępne informacje, jak i późniejsze działania.

Oddziel dane od zasad i uprawnień

Pobrana treść powinna dostarczać materiału do odpowiedzi, a nie stawać się źródłem uprawnień. Dokument może opisywać politykę firmy, ale aplikacja musi niezależnie ustalić, czy użytkownik ma prawo uzyskać dostęp do tego dokumentu lub wykonać powiązaną operację. Tej decyzji nie należy delegować treści ani wygenerowanej odpowiedzi.

  • Autoryzacja przed pobraniem: egzekwuj kontrolę dostępu podczas wyszukiwania i filtruj dokumenty zgodnie z tożsamością oraz aktualnymi uprawnieniami użytkownika.
  • Minimalny kontekst: przekazuj tylko fragmenty niezbędne do wykonania zadania. Nie dołączaj danych z innych kont, sekretów, poświadczeń ani informacji, których model nie potrzebuje.
  • Zasady poza modelem: obliczaj uprawnienia, limity i warunki biznesowe w kodzie aplikacji lub autoryzowanych usługach.
  • Odpowiedź jako propozycja: traktuj wynik modelu jako treść wymagającą walidacji, a nie jako instrukcję do wykonania.

Instrukcja systemowa może pomóc opisać oczekiwane zachowanie, na przykład wskazując, że pobrany tekst jest materiałem referencyjnym. Nie stanowi jednak granicy bezpieczeństwa: nie gwarantuje, że model zignoruje złośliwe instrukcje, ani nie zastępuje kontroli dostępu, walidacji i ograniczeń technicznych.

Projektowanie przepływu w PHP z wyraźnymi granicami

W PHP warto oddzielić etapy autoryzacji, pobierania danych, budowania kontekstu, wywołania modelu i walidacji wyniku. Taki podział ułatwia testowanie każdej granicy i zapobiega bezpośredniemu połączeniu wyniku AI z wrażliwą operacją.

Poniższy fragment to ilustracyjny pseudokod, a nie wykonywalne wywołanie konkretnego klienta. Sposób budowania żądania i akceptowane pola zależą od używanego API i SDK:

$user = $auth->currentUser();
$documents = $repository->searchAuthorized($user, $question);
$snippets = $contextBuilder->selectRelevant($documents, $maxItems);

// Pseudokod: dostosuj żądanie do konkretnego API.
$response = $aiClient->answer([
    'task' => 'Odpowiedz na podstawie materiału referencyjnego; nie autoryzuj działań.',
    'untrusted_context' => $snippets,
    'question' => $question,
]);

$answer = $responseValidator->validate($response);
return $answer;

Nazwy użyte w przykładzie mają charakter ilustracyjny. Oznaczenie kontekstu jako niezaufanego pomaga określić jego rolę, ale nie izoluje go niezawodnie: ani format, ani instrukcje same w sobie nie uniemożliwiają modelowi wykonania osadzonej instrukcji. Skuteczna separacja zależy również od wysyłanych danych, uprawnień egzekwowanych poza modelem i dostępnych możliwości.

Przed dodaniem wyodrębnionej treści do kontekstu normalizuj ją i ograniczaj: ustal maksymalne rozmiary, usuwaj formaty, których nie potrzebujesz, i ostrożnie traktuj tekst uzyskany przez OCR lub ze stron zewnętrznych. Nie łącz dokumentów bez limitów ani domyślnie nie dołączaj całej historii rozmowy. Zachowuj odniesienie do źródła każdego fragmentu, jeśli potrzebujesz wyjaśnić lub audytować odpowiedź, nie umieszczając w logach jego wrażliwej treści.

Ograniczanie skutków zmanipulowanej odpowiedzi

Ogranicz dostępne dla modelu narzędzia do tych niezbędnych w konkretnej funkcji. Jeśli zadanie wymaga tylko odpowiadania na pytania, nie udostępniaj narzędzi do zapisu ani ogólnego dostępu do usług wewnętrznych. Jeśli model musi odczytywać dane, udostępnij ograniczoną operację, która stosuje autoryzację dla każdego żądania, zamiast szerokich poświadczeń lub dowolnego dostępu do bazy danych.

Gdy model zaproponuje działanie, aplikacja musi zweryfikować je w niezależnym przepływie. W chwili wykonania sprawdź tożsamość, uprawnienia, parametry, reguły biznesowe i aktualne warunki dotyczące zasobu. W przypadku działań o dużym wpływie wymagaj wyraźnego potwierdzenia lub weryfikacji przez człowieka. Odpowiedź tekstowa modelu, nawet jeśli wygląda na bezpieczną lub cytuje dokument, nie zastępuje takiej autoryzacji.

Waliduj również wynik przed jego wyświetleniem lub przetworzeniem: sprawdzaj oczekiwany format, ograniczaj długość i odrzucaj pola lub wartości spoza dozwolonego zakresu. Jeśli oczekiwana jest konkretna struktura, parsuj jej pola i waliduj je za pomocą deterministycznych reguł. Nadal niezbędne są escapowanie danych wyjściowych w odpowiednim kontekście oraz zabezpieczenia przed iniekcją do HTML, SQL lub poleceń; generowanie przez AI nie sprawia, że wygenerowany tekst staje się zaufany.

Testowanie ataków i oczekiwanych zachowań

Testy powinny obejmować cały przepływ, a nie tylko sprawdzać, czy model prawidłowo reaguje na instrukcję systemową. Przygotuj nieszkodliwe i złośliwe dokumenty, które próbują zmienić zadanie, zażądać nieautoryzowanych danych lub skłonić do działania. Uwzględnij różne formaty źródłowe, takie jak tekst wyodrębniony z HTML, długie dokumenty oraz treści, w których instrukcje przeplatają się z uzasadnionymi informacjami.

  • Sprawdź, czy wyszukiwanie nigdy nie zwraca dokumentów spoza uprawnień użytkownika, nawet gdy pytanie wyraźnie żąda tych danych.
  • Zweryfikuj, czy złośliwe dokumenty nie odblokowują narzędzi ani nie zmieniają reguł biznesowych.
  • Potwierdź, że nieprawidłowa lub nieoczekiwana odpowiedź jest odrzucana, a wrażliwa operacja wymaga niezależnej autoryzacji.
  • Oceń użyteczność i poprawność odpowiedzi dla nieszkodliwych dokumentów, aby wykryć, czy ograniczenia nie pogarszają funkcji w nieakceptowalnym stopniu.
  • Powtarzaj testy po zmianie modelu, szablonu instrukcji, mechanizmu wyszukiwania, narzędzi lub procesu ekstrakcji.

Ustal obserwowalne kryteria akceptacji: jakie dane nigdy nie mogą się pojawić, jakie działania muszą pozostać zablokowane oraz jak system powinien odpowiadać, gdy brakuje wystarczających dowodów. Pojedynczy test nie gwarantuje bezpieczeństwa, ale powtarzalny zestaw testów pomaga wykrywać regresje i porównywać zmiany konfiguracji.

Rejestrowanie sygnałów bez gromadzenia wrażliwych danych

Na potrzeby analizy awarii rejestruj identyfikatory żądań, wersję konfiguracji, identyfikatory lub wewnętrzne odwołania do sprawdzanych dokumentów, decyzje autoryzacyjne, wywołane narzędzia i wyniki walidacji. Zapisanie odwołania nie oznacza przechowywania dokumentu ani jego fragmentów. Unikaj zapisywania wrażliwych fragmentów, chyba że istnieje konkretna potrzeba oraz odpowiednie kontrole dostępu, ochrony i retencji.

Dodaj metryki odrzuceń, błędów formatu i awarii dostawcy, aby odróżniać problemy bezpieczeństwa od problemów operacyjnych. Unikaj automatycznego zapisywania pełnych promptów, dokumentów i odpowiedzi, jeśli zawierają dane osobowe, tajemnice handlowe lub informacje podlegające regulacjom. Określ zasady retencji, dostępu oraz maskowania lub usuwania wrażliwych danych z logów; jeśli to wystarczy, rejestruj hashe, identyfikatory i ustrukturyzowane zdarzenia. Zadbaj, by logi nie stały się nowym sposobem ujawnienia treści, którą funkcja miała chronić.

Lista kontrolna przed udostępnieniem funkcji

Lista kontrolna przed udostępnieniem funkcji — guía visual de DedicatedPHP
  • Czy uprawnienia są sprawdzane przed pobraniem każdego dokumentu?
  • Czy wysyłany kontekst jest minimalny, ograniczony i traktowany jako niezaufane dane wejściowe?
  • Czy zasady i reguły biznesowe są egzekwowane poza modelem?
  • Czy narzędzia są ograniczone, a autoryzacja ponownie sprawdzana przy każdej operacji?
  • Czy odpowiedzi są walidowane przed wyświetleniem lub przekształceniem w działania?
  • Czy w przypadku decyzji o dużym wpływie wymagana jest weryfikacja przez człowieka lub potwierdzenie?
  • Czy istnieją powtarzalne testy złośliwych dokumentów i logi z kontrolowaną retencją?

Jeśli na którekolwiek pytanie odpowiedź brzmi „nie”, ogranicz zakres funkcji albo pozostaw działania w trybie propozycji do czasu usunięcia tej luki. Ochrona przed prompt injection w dokumentach nie zależy od tego, czy model zawsze prawidłowo zinterpretuje treść: zależy od tego, czy granice dostępu i operacji pozostaną skuteczne nawet wtedy, gdy model popełni błąd.

Chcesz zastosować te pomysły w swoim projekcie?Omówmy Twoją platformę PHP.
Zobacz powiązaną usługę