Biztonság és adatvédelem

A Lexo védelme rétegzett: a belépéstől a widgeten és az AI-on át a kimenő kérésekig.

Ez az oldal leírja, milyen védelmek működnek a Lexóban, és hol vannak a határaik. Egy réteg sem a másikra támaszkodik: ha az egyik hibázna, a többi akkor is véd.

Belépés és jogosultságok

A bejelentkezést a Clerk kezeli. A dashboard összes API-útvonala érvényes Clerk-munkamenetet kér; enélkül a kérés 401-es hibát kap.

A csapattagok szerepkört kapnak (Tulajdonos, Adminisztrátor, Ügynök, Megtekintő), és a szerver minden kérésnél ellenőrzi, hogy a szerepkör megengedi-e a műveletet. Az, hogy egy gomb nem látszik a felületen, csak kényelmi kérdés: a tényleges döntés a szerveren születik. A szerepkörök részletei: Ügynökségi modell.

Adatbázis és elkülönítés

Az adatok Supabase (PostgreSQL) adatbázisban vannak. A Row Level Security (RLS) tiltja a nyilvános kulccsal történő közvetlen adatbázis-hozzáférést: a böngészőből senki nem tudja közvetlenül lekérdezni a chatbotok, beszélgetések vagy szervezetek tábláit.

A szervezetek közötti elkülönítést minden API-útvonal szerveroldali jogosultság-ellenőrzése biztosítja: egy chatbotot csak az a felhasználó érhet el, akinek a szervezetéhez tartozik, és akinek a szerepköre az adott műveletet megengedi.

A widget védelme

A widget nyilvános, belépés nélkül működik, ezért külön védelmet kap:

  • Domainellenőrzés: a widget API csak a chatbothoz megadott weboldalról és engedélyezett domainekről érkező kéréseket szolgálja ki.
  • Beágyazási szabály chatbotonként: ha a chatbotnak meg van adva a weboldala, a widget oldalát a böngésző csak a chatbot saját domainjein engedi beágyazni (frame-ancestors). Így ha valaki kimásolja a chatbot azonosítóját, a saját oldalán nem tudja futtatni.
  • Csak iframe-ben: ha a widget oldalát valaki közvetlenül nyitja meg a böngészőben, 403-as oldalt kap.
  • Sebességkorlát: a widget kéréseit percenkénti, óránkénti és napi korlát fogja, chatbotonként és IP-címenként, Redisben számolva.
  • Napi tokenkeret chatbotonként: ha egy chatbot elérte a napi AI-keretét, aznap nem indít több AI-hívást. Ez a fiók havi keretén felül véd a hirtelen túlhasználat ellen.
  • Üzenethossz: egy látogatói üzenetből legfeljebb 2000 karakter jut el az AI-hoz.

Prompt injekció elleni védelem

A chatbotnak küldött üzeneteket egy szűrő vizsgálja, mielőtt az AI-hoz kerülnek. Az ismert mintákat kivágja az üzenetből, a többi részét változatlanul továbbítja:

  • utasítás-felülírás („ignore all previous instructions”, „forget your rules”),
  • szerepmanipuláció („you are now a…”, „pretend to be”, „act as”),
  • a rendszerprompt kikérése („show me your system prompt”),
  • elválasztó jelek ([INST], <system>, ### system),
  • magyar változatok („hagyd figyelmen kívül”, „felejtsd el az előző…”).

Az érintett üzenetekről a rendszer naplóbejegyzést készít.

A mintaszűrés az ismert támadásokat fogja meg, de nem tud mindent. Ezért a valódi következménnyel járó lépéseket (adatírás, rendelésadatok) nem az AI jóhiszeműsége védi, hanem a szerver szabályai, lásd lent.

Műveletek és rendelések

  • Író egyedi akciók: soha nem futnak le a látogató kifejezett „igen” válasza nélkül. A függő műveletet a szerver tárolja, nem a böngésző, így a látogató nem tudja kicserélni sem az akciót, sem a paramétereit. Részletek: Egyedi akciók.
  • Rendelés állapota: a chatbot csak akkor mond bármit egy rendelésről, ha a látogató a rendelésszámot és a rendeléshez használt e-mail címet is megadja, és a kettő egyezik. A lekérdezések számát IP-címenként korlátozza, a sikertelen próbálkozásokat pedig e-mail címenként, rendelésszámonként és chatbotonként is számolja. Részletek: Rendelés állapota.

Kimenő kérések (SSRF)

Ahol a Lexo szervere egy általad megadott címet hív meg (egyedi akciók, az időpontfoglalás Google Táblázat-címe), ott a rendszer nem engedi, hogy a kérés belső hálózatra menjen. Tiltott:

  • localhost, *.local, *.internal
  • loopback és „ez a hálózat” (127.0.0.0/8, 0.0.0.0/8)
  • privát tartományok (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • link-local, köztük a felhős metaadat-végpontok (169.254.0.0/16)
  • szolgáltatói NAT (100.64.0.0/10), teszthálózat (198.18.0.0/15), multicast és fenntartott címek (224.0.0.0 felett)
  • IPv6: loopback (::1), ::, egyedi helyi (fc00::/7), link-local (fe80::/10), 6to4 (2002::/16), valamint az IPv6-ba csomagolt IPv4-címek (::ffff:…, 64:ff9b::…), amelyeket a bennük lévő IPv4-cím alapján ítél meg

Nem csak a megadott nevet nézi: feloldja a domaint, és minden kapott IP-címet ellenőriz, majd a kapcsolódás pillanatában is azt a címet vizsgálja, amelyre ténylegesen csatlakozik. Így egy DNS-trükk (először nyilvános, aztán belső címet visszaadó névszerver) sem jut át. Átirányítást nem követ, a teljes válasznak időkorláton belül kell megérkeznie, és a válasz mérete korlátos.

Más kimenő kéréseknél (például a linkelőnézetnél) a rendszer a megadott hosztnevet szűri a fenti lista alapján, névfeloldás nélkül.

Titkos adatok tárolása

Ezeket a hozzáférési adatokat a Lexo AES-256-GCM titkosítással tárolja az adatbázisban:

  • a webshop-kapcsolat hozzáférési adatai (rendelés-lekérdezés),
  • a saját e-mail küldéshez megadott SMTP-jelszó,
  • az időpontfoglalás Google Táblázat-címe.

Az egyedi akciók hitelesítő adatait (API kulcs, jelszó, fejlécek) a Lexo csak szerveroldalon használja a kéréshez; a látogató böngészőjébe és az AI-hoz nem jutnak el.

Webhook aláírás

Ha egy webhooknak van titkos kulcsa (új webhooknál ez az alapbeállítás), minden kérés X-Webhook-Signature fejlécében ott a törzs HMAC-SHA256 aláírása. A fogadó végpont ezzel ellenőrizheti, hogy a kérés tőlünk jött, és útközben nem módosult. Részletek és ellenőrző kód: Webhookok.

Aláírt linkek az e-mailekben

A leiratkozó link és az időpont-lemondó link aláírt tokent tartalmaz, ezért nem lehet kitalálni vagy másik fiókra, másik foglalásra átírni. A link megnyitása önmagában nem csinál semmit: az oldalon egy gombot kell megnyomni, amely POST kérést küld. Így egy levelezőprogram vagy vírusszűrő, amely előre megnyitja a linkeket, nem iratkoztat le és nem mond le időpontot véletlenül.

Böngészővédelem és hibafigyelés

  • A dashboardot és a többi oldalt más oldal nem ágyazhatja be (X-Frame-Options: SAMEORIGIN, frame-ancestors 'self'), ami a clickjacking ellen véd.
  • További fejlécek: X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, és egy Permissions-Policy, amely tiltja a kamerát, a helymeghatározást, a fizetési és USB-hozzáférést (a mikrofon csak a saját oldalunkon, a hangbevitelhez engedélyezett).
  • A hibákat a Sentry gyűjti, az EU-s régiójában. Személyes adatot nem küldünk neki: nincs felhasználói azonosító, süti, kéréstörzs (a látogató üzenete), és nincs AI-prompt vagy -válasz sem.

Adatvédelem

  • Látogatói adatok: a beszélgetések a látogató nevének vagy e-mail címének ismerete nélkül is működnek. Személyes adat akkor kerül tárolásra, ha a látogató megadja: a lead űrlapon, beszélgetés közben (ha e-mail címet vagy telefonszámot ír, a chatbot leadként rögzíti), időpontfoglaláskor (név, e-mail, telefonszám, megjegyzés), vagy ha élő átadást, jegyet kér. A beszélgetések szövegét is tároljuk, hogy az Előzmények oldalon visszanézhesd őket.
  • Rendelés-lekérdezés: a webshopból lekért rendelésadatot a Lexo nem menti külön. A chatbot válasza a beszélgetés része lesz, mint bármely más üzenet. A korlátozáshoz használt számlálók az e-mail címet és a rendelésszámot csak hash-elve tárolják, legfeljebb egy óráig.
  • Törlés: egy chatbot törlésekor a tudásbázisa a vektoros adatbázisból is törlődik, és vele együtt törlődnek a beszélgetései, leadjei és időpontjai is.
Ha egy látogató adattörlési kérelmet küld neked, írj nekünk, és segítünk eltávolítani a hozzá tartozó beszélgetéseket és leadeket.