Az anyag a 2026. október 20-i állapotot tükrözi. Listák, verziószámok és határidők gyorsan változnak, ezért ügyfél elé vagy auditba kerülő anyagban a hivatkozott rangsort és dátumot érdemes a forrásnál újra ellenőrizni (genai.owasp.org, owasp.org, modelcontextprotocol.io, eur-lex.europa.eu, nist.gov).
Az alapmodell. Az LLM megbízhatatlan, befolyásolható komponens
Az összes további szabály egyetlen fenyegetési modellből következik.
- Az LLM nem tud megbízhatóan különbséget tenni utasítás és adat között. A system prompt, a felhasználó üzenete, a letöltött weboldal, az email törzse és a tool eredménye ugyanabba a tokenfolyamba kerül. Bármelyik darabja utasításként hathat.
- A modell kimenete nem determinisztikus és tévedhet. Ugyanarra a bemenetre más választ adhat, magabiztosan állíthat valótlant, kitalálhat függvényt, csomagot, paramétert.
- Ami a kontextusban van, az kiszivároghat. Ha a modell látja, akkor egy ügyes bemenet ki is írathatja, és ha van kifelé vezető csatorna, el is küldheti.
- Az ügynök jogosultsága a legrosszabb bemenet jogosultsága. Ha egy ügynök olvas nem megbízható tartalmat, és közben eszközöket hívhat, akkor a nem megbízható tartalom szerzője is hívhatja ezeket az eszközöket.
Ebből következik a mérnöki hozzáállás. Az LLM-et úgy kezeljük, mint egy rendkívül tehetséges, de befolyásolható gyakornokot, akinek a kezébe adott minden kulcsot egy idegen is elkérhet. A biztonságot ezért nem a modellbe, hanem a modell köré építjük. Jogosultságról, validációról és visszafordíthatatlan lépésekről determinisztikus kód dönt.
Tipikus hiba. Gyakori, hogy a biztonsági szabályt a system promptba írjuk (például azt, hogy soha ne törölj adatot), és ezt védelemnek tekintjük. A system prompt azonban kérés, nem kényszer. Kényszer csak a kódban és az infrastruktúrában létezik.
OWASP Top 10 for LLM Applications. A 2025 és a 2026 kiadás
Mi változott
Az OWASP GenAI Security Project 2024 végén adta ki a 2025-ös listát. A 2026-os kiadás 2026 augusztusának elején jelent meg. Mind a tíz kategória megmaradt, új kategória nem jött, a sorrend viszont jelentősen átrendeződött. Ez volt az első kiadás, amelyben a közösségi szavazást (75 százalék) valós, katalogizált AI incidensek adataival (25 százalék) súlyozták. Legnagyobbat az Excessive Agency mozdult, a 6. helyről a 3.-ra emelkedett, mert egyre több LLM alkalmazás hív eszközöket. A System Prompt Leakage új neve Hidden Context Exposure, és már minden, a felhasználó elől rejtett kontextust lefed (memória, visszakeresett dokumentum, tool kimenet, beszélgetés előzmény). Az Improper Output Handling az 5. helyről a 10.-re esett, de a hatóköre bővült, már kifejezetten tartalmazza a terminál és IDE kimenetet (ANSI escape szekvenciák) és az automatikusan külső erőforrást letöltő renderelőket.
2026 október elején a genai.owasp.org listaoldala még a 2025-ös számozást mutatta, miközben a projekt oldalán már a 2026-os kiadás szerepelt. Mindkét számozás forgalomban van, ezért hivatkozáskor az évszámot mindig kiírjuk (LLM03:2026, LLM06:2025).
| 2026 | Kategória | 2025 | Lényeges változás |
|---|---|---|---|
| LLM01 | Prompt Injection | LLM01 | Bővült, multimodális támadások, memóriában megmaradó injekció, ügynöki hatósugár |
| LLM02 | Sensitive Information Disclosure | LLM02 | Változatlan hely |
| LLM03 | Excessive Agency | LLM06 | A legnagyobb emelkedés, hivatkozik az Agentic Top 10 listára |
| LLM04 | Supply Chain | LLM03 | Bekerült a modell és artefaktum bizalmi hiba |
| LLM05 | Data and Model Poisoning | LLM04 | Elnyelte a finomhangolás alattomos manipulálását |
| LLM06 | Unbounded Consumption | LLM10 | Átkeretezve, a szolgáltatásmegtagadás helyett a költség aszimmetria a fő gond |
| LLM07 | Misinformation | LLM09 | Az incidensadatok erősebbnek mutatták, mint a szavazás |
| LLM08 | Hidden Context Exposure | LLM07 (System Prompt Leakage) | Átnevezve és kiszélesítve |
| LLM09 | Vector and Embedding Weaknesses | LLM08 | Hatókör változatlan |
| LLM10 | Improper Output Handling | LLM05 | Hatókör bővült (ANSI, auto fetch renderelés) |
Tételenként. Mi ez, hogyan védekezünk, mi a tipikus hiba
LLM01 Prompt Injection. A bemenet felülírja a fejlesztő szándékát. Közvetlen formában a felhasználó írja be, közvetett formában egy dokumentum, weboldal, email vagy tool válasz hordozza. Részletes elemzése lent, a prompt injekciónál következik. Röviden a védekezés architekturális elválasztás (a nem megbízható tartalmat olvasó modell ne hívhasson veszélyes eszközt), legkisebb jogosultság, emberi jóváhagyás és a kimeneti csatornák szűkítése. Tipikus hiba, hogy egy szűrő prompttal vagy regexszel próbáljuk kiszűrni a támadó szöveget.
LLM02 Sensitive Information Disclosure. Személyes adat, titok, üzleti adat kerül a válaszba vagy a naplóba. Védekezés. Ami nem kell a feladathoz, az be sem kerül a kontextusba (adatminimalizálás a prompt összeállításakor). PII maszkolás a naplóban, bérlőnként elválasztott retrieval. A szolgáltatóval DPA, EU adatrezidencia és a tanításra való felhasználás kizárása. Tipikus hiba a teljes ügyféltábla beküldése azért, hogy a modell válogasson.
LLM03 Excessive Agency. Az ügynöknek túl sok funkciója, túl széles jogosultsága vagy túl nagy önállósága van. Három külön dimenzió, mindhármat külön szűkítjük. Kevesebb eszköz (excessive functionality), szűkebb token és adatbázis jog (excessive permissions), jóváhagyás a hatással járó lépés előtt (excessive autonomy). Tipikus hiba egy általános run_sql vagy http_request eszköz, amikor három konkrét, paraméterezett lekérdezés elég lenne.
LLM04 Supply Chain. Kompromittált modell, adapter, adatkészlet, csomag, MCP szerver, prompt sablon. Védekezés. Rögzített verzió és hash, ismert forrás, SBOM és AIBOM, a modell és az MCP szerver eredetének ellenőrzése. Tipikus hiba egy GitHubról talált MCP szerver npx paranccsal, verzió rögzítése nélkül.
LLM05 Data and Model Poisoning. A tanító, finomhangoló vagy RAG adatba juttatott rosszindulatú tartalom. Egy tanácsadói projektnél a RAG korpusz és az ügynöki memória a valós támadási felület, nem a modell tanítása. Védekezés. Csak ellenőrzött forrásból indexelünk, minden chunk őrzi a forrását és a feltöltőjét, a memóriába írás validált és visszakereshető.
LLM06 Unbounded Consumption. Elszabaduló költség és erőforrás. Egy ügynök hurokba kerül, egy támadó drága kéréseket küld, egy RAG lekérdezés száz dokumentumot tölt be. Védekezés. Felhasználónkénti rate limit, kérésenkénti max_tokens, lépésszám limit, napi költségkeret szolgáltatói és alkalmazás szinten, riasztás. Tipikus hiba, hogy a limit csak a szolgáltatói konzolon van beállítva, az alkalmazásban nincs.
LLM07 Misinformation. Hallucináció, kitalált hivatkozás, túl magabiztos hamis állítás. Védekezés. Forráshoz kötött válasz (grounding) idézett forrásazonosítóval, a forrás létezésének programozott ellenőrzése, a bizonytalanság kimondásának engedélyezése a promptban, és a magas tétű döntésnél ember. A technikák részletesen a kimenet strukturálásánál és a hallucináció kezelésénél szerepelnek.
LLM08 Hidden Context Exposure. A system prompt, a memória, a visszakeresett dokumentum vagy a tool kimenet kiolvasható. Védekezés. A system promptba nem teszünk titkot, kulcsot, belső URL-t, jogosultsági logikát. Abból indulunk ki, hogy minden, ami a kontextusban van, nyilvános lehet annak, aki a modellel beszél. Tipikus hiba, hogy a system prompt tartalmazza a ki mit láthat szabályt, és ezt a modell tartatja be.
LLM09 Vector and Embedding Weaknesses. Bérlők közötti szivárgás a vektor adatbázisban, embedding inverzió, mérgezett dokumentum a korpuszban. Védekezés a RAG biztonságnál (jogosultság a retrieval szintjén, RLS a vektortáblán).
LLM10 Improper Output Handling. A modell kimenetét validálás nélkül adjuk tovább egy értelmezőnek. HTML (XSS), SQL, shell, fájlút, URL, markdown kép, terminál ANSI kód. Védekezés. A kimenet ugyanolyan nem megbízható bemenet, mint egy űrlapmező. Kontextusnak megfelelő escape, paraméterezett lekérdezés, allowlist a külső URL-ekre, CSP. A 2026-os bővítés miatt a CLI eszközökben a modell kimenetéből az ANSI vezérlőkódokat is kiszűrjük.
// LLM10. A modell kimenete nem megbízható bemenet
import DOMPurify from "isomorphic-dompurify";
const ALLOWED_IMG_HOSTS = new Set(["cdn.sajatdomain.hu"]);
export function safeRenderMarkdownHtml(html: string): string {
// 1) HTML tisztítás, script és eseménykezelő ki
const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true } });
// 2) Külső képek tiltása. A markdown kép a klasszikus adatkiszivárogtató csatorna,
// mert a böngésző magától letölti, és az URL query része viheti az adatot.
return clean.replace(/<img[^>]+src="([^"]+)"[^>]*>/g, (tag, src) => {
try {
return ALLOWED_IMG_HOSTS.has(new URL(src).host) ? tag : "";
} catch {
return "";
}
});
}
// Terminálba írt modell kimenet. ANSI és egyéb vezérlőkarakterek ki.
export function stripControl(s: string): string {
return s.replace(/\x1b\[[0-9;?]*[ -\/]*[@-~]/g, "").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
}
A kódminta mellé a böngészőben CSP is kell (img-src 'self' cdn.sajatdomain.hu; connect-src 'self'), mert a regex csak egy réteg.
OWASP Top 10 for Agentic Applications 2026
A lista 2025. december 9-én jelent meg az OWASP GenAI Security Project Agentic Security Initiative munkacsoportjától. Nem helyettesíti az LLM Top 10 listát, hanem kiegészíti azzal, ami akkor jelenik meg, amikor a modell tervez, eszközt hív, memóriát ír és más ügynökkel beszél. A tételek azonosítója ASI01 és ASI10 között fut.
| Azonosító | Kockázat | Mit jelent a gyakorlatban | Fő védekezés |
|---|---|---|---|
| ASI01 | Agent Goal Hijack | Az olvasott tartalom átírja az ügynök célját, az ügynök közben azt hiszi, a felhasználót szolgálja | Bizalmi szétválasztás, cél és terv rögzítése a nem megbízható adat beolvasása előtt |
| ASI02 | Tool Misuse and Exploitation | Jogos eszköz rossz használata, hurok, veszélyes láncolás, tömeges hívás | Szűk eszközök, paraméter validáció, hívásszám limit |
| ASI03 | Identity and Privilege Abuse | Tisztázatlan ügynök identitás, delegált jog visszaélése | Ügynökönkénti identitás, rövid életű, szűk hatókörű token |
| ASI04 | Agentic Supply Chain Vulnerabilities | Importált ügynök, eszköz, séma, prompt kompromittálódik | Aláírt komponens, verzió rögzítés, AIBOM |
| ASI05 | Unexpected Code Execution | Az ügynök által generált vagy indított kód izoláció nélkül fut | Sandbox, alapból tiltott kimenő hálózat |
| ASI06 | Memory and Context Poisoning | A memóriába írt injekció később is irányít | Validált memóriaírás, forrás jelölés, lejáró kontextus |
| ASI07 | Insecure Inter Agent Communication | Ügynökök közti üzenet hamisítható, módosítható | Kölcsönös hitelesítés, aláírt üzenet, séma |
| ASI08 | Cascading Failures | Kis hiba végigfut az összekötött eszközökön | Hatósugár izoláció, circuit breaker |
| ASI09 | Human Agent Trust Exploitation | Az ember ellenőrzés nélkül elfogadja a magabiztos kimenetet | Kötelező megerősítés, a jóváhagyó képernyő a tényleges hatást mutatja |
| ASI10 | Rogue Agents | Az ügynök a szándékolt viselkedésén kívül működik | Viselkedésfigyelés, kill switch |
Hogyan használjuk tervezéskor
- Minden ügynökhöz kitöltjük a tervezési kártyát. A kártya (lent, a gyakorlati szabályok között) kérdései az ASI tételekre képeződnek le.
- ASI01 és ASI06 ellen a terv rögzítése. Az ügynök a felhasználói kérésből először tervet készít, a tervet a kód rögzíti, és a nem megbízható tartalom beolvasása után már csak a rögzített terv lépései futhatnak (Plan Then Execute minta, lásd a prompt injekció elleni tervezési mintáknál).
- ASI03 ellen nincs közös szolgáltatói kulcs. Az ügynök a felhasználó nevében, a felhasználó jogával, rövid életű tokennel dolgozik. Supabase esetén ez a felhasználó JWT-je és RLS, nem a
service_rolekulcs. - ASI08 ellen circuit breaker. Ha egy eszköz egymás után háromszor hibázik, vagy egy lépés háromszor ismétlődik azonos paraméterrel, az ügynök megáll és emberhez fordul.
- ASI09 ellen a jóváhagyó képernyő a tényleges műveletet mutatja. Nem a modell összefoglalóját (például azt, hogy elküldöm a választ), hanem a címzettet, a tárgyat, a teljes szöveget és a csatolmányt. A modell összefoglalója maga is támadási felület.
- ASI10 ellen kill switch. Egy feature flag vagy adatbázis kapcsoló, ami az összes futó ügynököt leállítja, és amit a kód minden lépés előtt ellenőriz.
Tipikus hiba. Több ügynökös rendszert építünk (orchestrator és alügynökök), mert elegánsnak tűnik, és ezzel megnyitjuk az ASI07 és ASI08 felületét egy olyan feladatnál, ahol egy workflow is elég lett volna.
OWASP MCP Top 10 és a GenAI Security Project egyéb anyagai
OWASP MCP Top 10
A lista létezik, de 2026 októberében még béta és pilot fázisban van (0.1 verzió, 2025). Élő dokumentumnak szánják, a számozás és a megfogalmazás változhat, ezért hivatkozás előtt ellenőrizendő.
| Azonosító | Kockázat | Ellenszer röviden |
|---|---|---|
| MCP01 | Token Mismanagement and Secret Exposure | Rövid életű, szűk token, titok nem kerül a kontextusba és a naplóba |
| MCP02 | Privilege Escalation via Scope Creep | Minimális scope, fokozatos jogkérés |
| MCP03 | Tool Poisoning | Tool leírás átnézése, rögzítése, változásfigyelés |
| MCP04 | Software Supply Chain Attacks and Dependency Tampering | Verzió és hash rögzítés, ismert kiadó |
| MCP05 | Command Injection and Execution | Nincs shell string összefűzés, argumentum tömb, allowlist |
| MCP06 | Intent Flow Subversion | A felhasználói szándék és a tool válasz bizalmi szétválasztása |
| MCP07 | Insufficient Authentication and Authorization | OAuth 2.1, audience ellenőrzés, nincs token passthrough |
| MCP08 | Lack of Audit and Telemetry | Minden tool hívás naplózva, korrelációs azonosítóval |
| MCP09 | Shadow MCP Servers | MCP szerver leltár, engedélyezett lista szervezeti szinten |
| MCP10 | Context Injection and Over Sharing | Csak a szükséges adat megy át a kontextusba |
A shadow MCP a shadow AI testvére. Egy cégnél a munkatársak saját MCP szervereket kötnek be az asztali AI kliensek (például Claude Desktop vagy Cursor) alá, amelyekről az IT nem tud. AI felmérésnél ez külön kérdés.
A GenAI Security Project további hasznos anyagai
| Anyag | Mire jó |
|---|---|
| Agentic AI Threats and Mitigations (2025) | Az ügynöki fenyegetési taxonómia, ebből nőtt ki az ASI lista |
| Securing Agentic Applications Guide | Gyakorlati tervezési és telepítési útmutató ügynökökhöz |
| LLM and GenAI Data Security Best Practices | Adatkezelés, maszkolás, adatfolyamok |
| AI Red Teaming útmutató és AI Testing Guide | Hogyan teszteljük támadói szemmel az LLM alkalmazást |
| LLM Applications Cybersecurity and Governance Checklist | Vezetői, governance szintű ellenőrzőlista, ügyfélnek jól átadható |
| AIVSS (AI Vulnerability Scoring System) | Sérülékenység pontozás ügynöki tényezőkkel kiegészítve |
Prompt injekció mélyen
Közvetlen és közvetett
Közvetlen injekció. A felhasználó maga írja be a támadó szöveget (jailbreak, a szabályok felülírására tett kísérlet). Egy belső eszköznél, ahol a felhasználó a saját adataihoz fér hozzá, ennek a kockázata kicsi, mert legfeljebb önmagát támadja.
Közvetett injekció. A támadó szöveg egy olyan forrásban ül, amit az ügynök a munkája közben olvas. Weboldal, beérkező email, PDF, GitHub issue, támogatási jegy, naptármeghívó, adatbázis sor, MCP tool válasz, képbe rejtett szöveg. A felhasználó ártatlan, az ügynök az ő jogaival hajtja végre a támadó kérését. Ez az ügynökök igazi problémája.
Valós esetek 2025 és 2026 között, amelyekből tanulni lehet.
- EchoLeak (Microsoft 365 Copilot, 2025). Egy beérkező email rejtett utasítása rávette az asszisztenst, hogy belső adatot egy külső URL-be kódolva kiküldjön, felhasználói kattintás nélkül.
- Supabase MCP szivárgás (2025 nyara). Egy fejlesztő
service_rolejogú MCP kapcsolattal olvastatta a támogatási jegyeket. Az egyik jegybe írt utasítás hatására az ügynök kiolvasta egy titkos tábla tartalmát és visszaírta a jegybe, ahol a támadó láthatta. Három összetevő volt együtt jelen, privát adat, nem megbízható tartalom és visszafelé írható csatorna. - GitHub MCP (2025). Egy nyilvános repóban nyitott issue utasítása arra vette rá a felhasználó ügynökét, hogy privát repók tartalmát egy nyilvános pull requestbe tegye.
Simon Willison lethal trifecta
Willison 2025 júniusában fogalmazta meg. Egy ügynök akkor kihasználható adatlopásra, ha egyszerre van meg benne a három képesség.
- Hozzáférés privát adathoz.
- Kitettség nem megbízható tartalomnak.
- Külső kommunikációs képesség (bármi, ami adatot visz ki, HTTP kérés, email küldés, markdown kép renderelése, link, PR nyitása, nyilvános bejegyzés írása).
A védekezés logikája determinisztikus. Egy munkamenetben a háromból legfeljebb kettő lehet jelen. Ha mindhárom kell, akkor a munkamenetet szétvágjuk, vagy a kifelé vezető lépést ember hagyja jóvá a tényleges tartalom láttán.
// Tervezési idejű ellenőrzés: a trifecta egy munkamenetben nem állhat össze
type Capability = "private_data" | "untrusted_input" | "external_comms";
interface ToolSpec {
name: string;
capabilities: Capability[];
requiresApproval?: boolean;
}
export function assertNoLethalTrifecta(tools: ToolSpec[]): void {
const caps = new Set(
tools.filter(t => !t.requiresApproval).flatMap(t => t.capabilities)
);
if (caps.has("private_data") && caps.has("untrusted_input") && caps.has("external_comms")) {
throw new Error(
"Lethal trifecta: privát adat + nem megbízható bemenet + külső kommunikáció jóváhagyás nélkül. " +
"A munkamenetet szét kell vágni, vagy emberi jóváhagyás kell a kifelé vezető eszközre."
);
}
}
Ezt a függvényt az ügynök konfigurációjának betöltésekor futtatjuk, nem futás közben, így a hibás összeállítás el sem indul.
Miért nem elég a szűrés
- A támadási tér végtelen. Természetes nyelven ugyanazt a szándékot számtalan formában lehet kifejezni, más nyelven, kódolva, versben, képben, több üzenetre szétosztva.
- A szűrő maga is LLM vagy statisztikai modell. Ugyanúgy megtéveszthető, mint a védett modell. Adaptív támadással a publikált guardrail modellek többsége megkerülhető.
- A biztonságban a 99 százalék megbukott jegy. Egy webes injekciós szűrő, ami a támadások 99 százalékát megfogja, egy SQL injekció elleni védelemnél elfogadhatatlan lenne. Támadónak elég egyszer sikerülnie, és automatizáltan próbálkozik.
- A szűrés hamis biztonságérzetet ad. Emiatt marad bent a veszélyes eszköz és a széles jogosultság.
Szűrő és detektor (például egy prompt shield) hasznos réteg lehet a zaj csökkentésére és a naplózásra, de a biztonsági garanciát az architektúra adja.
A dual LLM minta (Willison, 2023)
Két modellpéldány, eltérő bizalmi szinttel.
- Privilegizált LLM (P). Csak a felhasználótól és a fejlesztőtől kap szöveget, eszközt hívhat. Nem megbízható tartalmat soha nem lát.
- Karanténba zárt LLM (Q). Feldolgozza a nem megbízható tartalmat (összefoglal, kivonatol), de eszközt nem hívhat.
- A kettő között a kód áll. Q kimenetét P nem kapja meg szövegként, csak egy szimbolikus hivatkozást (
$VAR1). Csak a kód helyettesíti be a tényleges értéket abban a pillanatban, amikor a végső művelet fut, és a felhasználónak megmutatja.
// Dual LLM vázlat. P csak szimbólumokat lát, Q nem hív eszközt.
const vars = new Map<string, string>();
async function quarantinedSummarize(untrusted: string): Promise<string> {
const res = await anthropic.messages.create({
model: MODEL_Q, max_tokens: 800,
system: "Foglald össze a szöveget legfeljebb 5 mondatban. Csak összefoglalót adj vissza.",
messages: [{ role: "user", content: untrusted }],
// nincs tools paraméter: Q nem hívhat eszközt
});
const text = res.content.filter(b => b.type === "text").map(b => b.text).join("");
const key = `$VAR${vars.size + 1}`;
vars.set(key, text);
return key; // P csak ezt a kulcsot kapja
}
// P eszköze: összefoglaló küldése emailben. Az emailt a kód állítja össze,
// a tartalmat a felhasználó jóváhagyó képernyőn látja, mielőtt elmegy.
async function sendSummary(toUserSelf: boolean, varKey: string) {
if (!toUserSelf) throw new Error("Csak a felhasználó saját címére küldhető");
const body = vars.get(varKey);
if (!body) throw new Error("Ismeretlen változó");
await requireHumanApproval({ action: "email.send", to: currentUser.email, body });
await mailer.send({ to: currentUser.email, subject: "Összefoglaló", body });
}
Korlátja, hogy P nem tud a tartalom alapján dönteni (például arról, hogy a levél sürgős-e), mert nem látja. Ahol erre szükség van, ott Q strukturált, szűk értékkészletű kimenetet ad ("sürgős" | "normál" enum), és az enum értéket már átadhatjuk P-nek, mert abban nincs hely utasításnak.
CaMeL (Google DeepMind és ETH Zürich, 2025)
Debenedetti és mtsai, Defeating Prompt Injections by Design (2025 március). A dual LLM minta szigorú, programozási nyelvi megvalósítása.
- A privilegizált LLM a felhasználói kérésből programot ír (egy korlátozott Python részhalmazban), ez rögzíti a vezérlési folyamatot, mielőtt bármilyen nem megbízható adat beérkezne.
- Egy egyedi értelmező futtatja a programot. A nem megbízható adat feldolgozásához a karanténba zárt LLM-et hívja, amelynek kimenete csak adat lehet, vezérlést nem módosíthat.
- Minden érték képességcímkét (capability) visz magával. A címke rögzíti, honnan jött az adat és kinek adható tovább.
- Az eszközhívás előtt biztonsági szabály fut. Például az, hogy egy nem megbízható forrásból származó email cím nem lehet egy belső dokumentum küldésének címzettje.
CaMeL az AgentDojo benchmarkon a feladatok 77 százalékát oldotta meg bizonyítható biztonsággal, szemben a védelem nélküli rendszer 84 százalékával. Tanácsadói projektben ritkán telepítünk CaMeL-t, az elveit viszont átvesszük. A terv a nem megbízható adat előtt készül el, az adat címkét visz, és az eszközhívás előtt determinisztikus szabály dönt.
// CaMeL elv kicsiben: értékek eredetcímkével, szabály az eszközhívás előtt
type Origin = "user" | "trusted_db" | "untrusted_web" | "untrusted_email";
interface Tainted<T> { value: T; origins: Set<Origin> }
const isUntrusted = (t: Tainted<unknown>) =>
[...t.origins].some(o => o.startsWith("untrusted"));
function policySendEmail(to: Tainted<string>, body: Tainted<string>) {
if (isUntrusted(to)) {
throw new PolicyViolation("Címzett nem jöhet nem megbízható forrásból");
}
if (body.origins.has("trusted_db") && !ALLOWED_DOMAINS.has(to.value.split("@")[1])) {
throw new PolicyViolation("Belső adat csak engedélyezett domainre mehet");
}
}
Design Patterns for Securing LLM Agents against Prompt Injections (2025)
Beurer-Kellner és mtsai (IBM, Invariant Labs, ETH Zürich, Google, Microsoft és mások), 2025 június. Közös elvük, hogy amint az ügynök nem megbízható bemenetet olvasott, korlátozni kell, mit tehet utána. Hat mintát írnak le, ezeket foglalja össze a táblázat.
| Minta | Hogyan működik | Mikor használjuk | Ár |
|---|---|---|---|
| Action Selector | Az LLM csak egy előre definiált akciólistából választ, a tool válasz nem jut vissza a modellhez | Ügyfélszolgálati bot, ami menüpontot vagy előre megírt műveletet indít | Nincs valódi rugalmasság |
| Plan Then Execute | A terv (eszközhívások sorrendje) a nem megbízható adat előtt rögzül, az adat a paramétereket befolyásolhatja, a lépéseket nem | Email asszisztens, ami naptárt olvas és összefoglalót küld | A paraméterek továbbra is manipulálhatók |
| LLM Map Reduce | Minden nem megbízható dokumentumot külön, eszköz nélküli LLM hívás dolgoz fel szűk sémára, az eredményt determinisztikus kód vagy egy tiszta LLM aggregálja | Száz önéletrajz vagy számla szűrése | Több hívás, több költség |
| Dual LLM | Privilegizált és karanténba zárt modell, szimbolikus változók | Összefoglalás, fordítás, válaszvázlat külső tartalomból | P nem lát bele a tartalomba |
| Code Then Execute | Az LLM programot ír, amit sandbox futtat, a nem megbízható adat csak adatként kerül a programba (CaMeL ide tartozik) | Összetett, többlépéses ügynök magas tétű adattal | Nagy fejlesztési ráfordítás |
| Context Minimization | A felhasználói prompt eltávolítása vagy szűkítése a további lépések kontextusából, így egy injektált kérés nem visz tovább | Lekérdezést generáló asszisztens, ahol a válasz már a lekérdezés eredményéből készül | Kontextusvesztés |
Választási sorrend a gyakorlatban.
- Action Selector, ha a feladat engedi.
- Plan Then Execute, ha rugalmasság kell.
- LLM Map Reduce, ha sok külső dokumentumot kell feldolgozni.
- Dual LLM vagy Code Then Execute, ha az előző három együtt sem elég.
// LLM Map Reduce: minden külső dokumentum külön, eszköz nélküli hívás, szűk séma
import { z } from "zod";
const InvoiceExtract = z.object({
vendorTaxId: z.string().regex(/^\d{8}-\d-\d{2}$/),
totalHuf: z.number().int().nonnegative().max(100_000_000),
dueDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
}).strict();
async function mapInvoice(pdfText: string) {
const res = await anthropic.messages.create({
model: MODEL_SMALL, max_tokens: 300,
system: "Számlaadat kinyerés. Csak a megadott JSON mezőket add vissza.",
messages: [{ role: "user", content: pdfText }],
});
const raw = res.content.find(b => b.type === "text")?.text ?? "";
return InvoiceExtract.safeParse(JSON.parse(raw)); // a séma kizárja a szabad szöveget
}
// Reduce: determinisztikus kód összesít, a modell nem látja egyszerre az összes dokumentumot.
Az adószám regex és a számtartomány a minta lényege. Szabad szöveges mező nélkül a dokumentumba rejtett utasításnak nincs hová kerülnie.
Tipikus hiba. A minta megvan, de egy mellékcsatorna megmarad. Például a karanténba zárt modell kimenete egy naplóba kerül, amit egy másik ügynök olvas, vagy a frontenden markdownként renderelődik külső képpel.
MCP biztonság
Mi az MCP és melyik verzió érvényes
A Model Context Protocol a modell alkalmazások és a külső eszközök, adatforrások közti szabványos protokoll (kliens, szerver, tools, resources, prompts). Verziói dátummal azonosítottak.
| Verzió | Ami biztonsági szempontból számít |
|---|---|
| 2025-03-26 | OAuth 2.1 alapú authorization HTTP transporthoz, stdio esetén a hitelesítő adat a környezetből jön |
| 2025-06-18 | Az MCP szerver OAuth Resource Server, Protected Resource Metadata (RFC 9728), kötelező Resource Indicators (RFC 8707) a kliensnek, külön Security Best Practices oldal, token passthrough kifejezetten tilos, structured tool output, elicitation |
| 2025-11-25 | OpenID Connect Discovery, fokozatos scope kérés WWW-Authenticate fejléccel, Client ID Metadata Documents (CIMD) ajánlott regisztrációs mód, URL módú elicitation, tool ikonok |
| 2026-07-28 | Állapotmentes protokoll, megszűnt a protokoll szintű session és az initialize kézfogás, a szerver által kiadott állapot handle közönséges tool argumentumként utazik, Dynamic Client Registration elavult a CIMD javára, az iss ellenőrzése kötelező (RFC 9207, mix up támadás ellen), Roots, Sampling és Logging elavult |
Új szervert a legfrissebb kiadott verzióra írunk, de a kliensek egy része még a régebbit beszéli. Az SDK verzióját és a támogatott protokollverziót a projekt dokumentációjában és az AI asszisztens projekt szintű kontextusfájljában is rögzítjük.
Tool poisoning
A tool leírása (description, paraméterleírás, akár a paraméter neve) a modell kontextusába kerül, és utasításként hat. Egy rosszindulatú szerver a leírásba rejtheti, hogy a modell olvassa el a ~/.ssh/id_rsa fájlt, és tegye a notes paraméterbe. A felületen a felhasználó csak a tool rövid nevét látja. Az Invariant Labs 2025-ben mutatta be a támadást, és azt is, hogy egy rosszindulatú szerver leírása egy másik, megbízható szerver eszközeinek használatát is befolyásolhatja (shadowing).
Hogyan védekezünk lépésről lépésre.
- Bekötés előtt elolvassuk a teljes
tools/listválaszt, nem a README-t. - Gyanús jelek. Utasító mondat a leírásban, rejtett vagy nem nyomtatható karakter, a feladathoz nem tartozó paraméter (
context,notes,sidenote), más eszközre vagy fájlútra hivatkozás. - A leírások hash-ét rögzítjük (pinning), és eltérés esetén a kliens nem indul el.
- Egy munkamenetbe csak annyi szervert kötünk, amennyi a feladathoz kell, mert minden szerver leírása minden másik eszköz használatára hatással lehet.
Rug pull
Jóváhagyás után a szerver megváltoztatja az eszközei leírását vagy viselkedését. A 2025-ös spec óta létező notifications/tools/list_changed (a 2026-07-28 verzióban subscriptions/listen) erre legitim csatornát ad. Csomagszinten ugyanez egy frissítéssel történik, ha nincs rögzített verzió.
// Tool leírás pinning: a jóváhagyott állapot hash-e a repóban él
import { createHash } from "node:crypto";
function toolFingerprint(tools: Array<{ name: string; description?: string; inputSchema: unknown }>) {
const canonical = JSON.stringify(
[...tools].sort((a, b) => a.name.localeCompare(b.name))
.map(t => ({ n: t.name, d: t.description ?? "", s: t.inputSchema }))
);
return createHash("sha256").update(canonical).digest("hex");
}
export async function verifyServer(client: McpClient, pinned: string) {
const { tools } = await client.listTools();
const fp = toolFingerprint(tools);
if (fp !== pinned) {
throw new Error(`MCP tool leírás változott (${fp.slice(0, 12)}). Átnézés és új pin kell.`);
}
}
Mellé a csomagverzió rögzítése (npx -y [email protected], nem @latest), és a lockfile.
Confused deputy
Klasszikus jogosultsági hiba (Hardy, 1988). Egy jogosult közvetítő rosszindulatú fél kérésére a saját jogával hajt végre műveletet. Az MCP spec két formában tárgyalja.
- OAuth proxy. Egy MCP szerver statikus client ID-val beszél egy harmadik fél authorization szerverével, közben a klienseknek dinamikus regisztrációt enged. A harmadik fél a korábbi beleegyezést sütiben tárolja. Ekkor a támadó regisztrál egy saját redirect URI-val, a felhasználónak linket küld, a beleegyezés képernyő kimarad, és az authorization kód a támadóhoz kerül. A spec szerint kötelező ellenszer a kliensenkénti beleegyezés az MCP szerver saját képernyőjén, mielőtt a harmadik félhez továbbít, a redirect URI pontos egyezése, az egyszer használatos
stateés a__Host-előtagú, aláírt süti. - Ügynöki confused deputy. Az ügynök a felhasználó jogával olvas egy támadó által írt tartalmat, és annak kérésére cselekszik. Ez a prompt injekció és a lethal trifecta jogosultsági megfogalmazása.
Token passthrough
Az MCP szerver elfogadja a klienstől kapott tokent anélkül, hogy ellenőrizné, neki adták-e ki, és továbbadja a downstream API-nak. A spec szerint az MCP szerver nem fogadhat el olyan tokent, amit nem kifejezetten neki adtak ki. Ennek hiányában a downstream rate limit és audit kijátszható, a naplóban nem látszik, ki kérte, és egy ellopott token proxyn keresztül használható.
// MCP szerver oldal: audience és issuer ellenőrzés, saját downstream token
import { jwtVerify, createRemoteJWKSet } from "jose";
const JWKS = createRemoteJWKSet(new URL("https://auth.sajatdomain.hu/.well-known/jwks.json"));
const MCP_RESOURCE = "https://mcp.sajatdomain.hu"; // RFC 8707 resource azonosító
export async function authenticate(req: Request) {
const auth = req.headers.get("authorization") ?? "";
const token = auth.startsWith("Bearer ") ? auth.slice(7) : null;
if (!token) throw new HttpError(401, "missing token");
const { payload } = await jwtVerify(token, JWKS, {
issuer: "https://auth.sajatdomain.hu",
audience: MCP_RESOURCE, // csak nekünk kiadott token
});
return { userId: String(payload.sub), scopes: String(payload.scope ?? "").split(" ") };
}
// Downstream hívásnál SOHA nem a bejövő tokent adjuk tovább.
// Saját, szűk hatókörű tokent cserélünk (token exchange, RFC 8693) vagy szerver oldali
// kliens hitelesítést használunk, és a userId alapján szűrünk.
SSRF és a többi spec szintű támadás
A 2026-07-28 Security Best Practices oldal további kötelező vagy erősen ajánlott tételei, amelyekre saját kliens vagy szerver írásakor figyelünk.
- SSRF az OAuth metaadat felderítésnél. A rosszindulatú szerver belső címre (
169.254.169.254,localhost:6379) mutató metaadat URL-t ad. Ellenszer a HTTPS kényszer, a privát IP tartományok tiltása, az átirányítások ellenőrzése, szerver oldali kliensnél egress proxy. Saját IP parser helyett bevált könyvtár. - State handle hijacking. Az állapotmentes protokollban a szerver által kiadott azonosító (kosár, workflow) nem hitelesítés. Véletlenszerű, lejáró handle kell, szerver oldalon a hitelesített felhasználóhoz kötve (
<user_id>:<handle>, a user ID a tokenből, nem a klienstől). - Authorization URL validáció. Csak
https(fejlesztéskor loopbackhttp),javascript:ésfile:séma tiltva, URL megnyitása shell nélkül. - Scope minimalizálás. Kis kezdő scope, fokozatos emelés, nincs
*vagyfull-access.
Helyi és távoli szerver
| Szempont | Helyi (stdio) | Távoli (Streamable HTTP) |
|---|---|---|
| Futás | A felhasználó gépén, a kliens jogával | Szolgáltatónál vagy saját szerveren |
| Fő kockázat | Tetszőleges kódfuttatás a gépen, fájlrendszer és SSH kulcs hozzáférés, rosszindulatú indító parancs | Hitelesítés, token kezelés, bérlők közti szivárgás, SSRF |
| Hitelesítés | Környezeti változó, a spec szerint nem az OAuth folyamat | OAuth 2.1, PKCE, audience kötött token |
| Kötelező védelem | Sandbox (konténer, korlátozott fájlrendszer és hálózat), rögzített verzió, a teljes indító parancs megmutatása jóváhagyás előtt | TLS, audience ellenőrzés, kliensenkénti beleegyezés, rate limit, audit napló |
| Ha HTTP-n fut helyben | Kötelező token vagy unix socket, különben DNS rebinding támadással egy weboldal is elérheti | Nem értelmezett |
Biztonságos MCP szerver váz (TypeScript)
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const server = new McpServer({ name: "kd-crm", version: "1.3.0" });
// Szűk, paraméterezett, csak olvasó eszköz. Nincs általános SQL.
server.registerTool(
"find_customer",
{
title: "Ügyfél keresése név alapján",
description: "Visszaadja a bejelentkezett felhasználó saját ügyfelei közül a névre illeszkedőket. Legfeljebb 10 találat.",
inputSchema: { query: z.string().min(2).max(80) },
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
},
async ({ query }, ctx) => {
const user = await authenticateFromContext(ctx); // audience ellenőrzött token
const db = supabaseAsUser(user.accessToken); // RLS érvényesül, nem service_role
const { data, error } = await db
.from("customers").select("id,name,city")
.ilike("name", `%${query.replace(/[%_]/g, "")}%`).limit(10);
if (error) return { isError: true, content: [{ type: "text", text: "Lekérdezési hiba" }] };
audit("find_customer", user.userId, { query, count: data.length });
return { content: [{ type: "text", text: JSON.stringify(data) }] };
}
);
A readOnlyHint és destructiveHint annotáció tájékoztató jellegű. Kliens oldalon felhasználható a jóváhagyási döntéshez, de a szerver nem bízhat abban, hogy a kliens betartja. Tényleges korlátot az RLS és a szűk eszköz ad.
Tipikus hibák MCP-nél. Egyetlen execute_sql eszköz service_role kulccsal. A kapott Bearer token továbbítása a Google API felé. npx -y valami-mcp verzió nélkül. Nyers HTML vagy markdown tool válasz, amit a kliens renderel. Stack trace és belső útvonal a hibaüzenetben.
Ügynök architektúra
Anthropic, Building Effective Agents (2024. december)
Az írás alapállítása, hogy a sikeres rendszerek egyszerű, összerakható mintákból épülnek, nem bonyolult keretrendszerekből. Két fogalmat választ szét. Workflow az, ahol az LLM és az eszközök előre megírt kódúton futnak. Agent az, ahol az LLM maga irányítja a folyamatot és az eszközhasználatot. Az alapelv, hogy a legegyszerűbb megoldással kezdünk, és csak akkor lépünk feljebb, ha mérhetően jobb eredményt hoz.
| Minta | Működés | Mikor jó | Biztonsági haszon |
|---|---|---|---|
| Prompt chaining | Lépések sorban, köztük programozott ellenőrző kapu | Jól felbontható feladat (vázlat, ellenőrzés, fordítás) | Minden lépés kimenete validálható |
| Routing | Osztályozó a bemenetet a megfelelő ágra küldi | Eltérő kezelést igénylő kategóriák (panasz, ajánlatkérés, számla) | Kis modell osztályoz, a veszélyes ág külön védhető |
| Parallelization | Párhuzamos részfeladatok (sectioning) vagy többszöri futás szavazással (voting) | Gyorsítás, több szempontú ellenőrzés | A voting egy guardrail réteg is lehet |
| Orchestrator workers | Központi LLM dinamikusan bont részfeladatokra, munkásoknak oszt | Előre nem ismert részfeladatok (több fájlos kódmódosítás) | Munkásonként szűkíthető jogosultság |
| Evaluator optimizer | Egy LLM generál, egy másik értékel és visszajelez, ciklusban | Világos értékelési szempontok, iteratív javítás | Ciklusszám limit kell |
| Autonomous agent | LLM ciklusban tool hívással, környezeti visszajelzés alapján | Nyitott végű feladat, nehezen előre jelezhető lépésszám | A legtöbb védelmet igényli |
Mikor elég egy workflow
Ezt a döntési sorrendet minden ügyfélprojektnél végigjárjuk.
- Megoldható egyetlen LLM hívással, jó prompttal, retrievallal és példákkal? Akkor nem építünk ügynököt.
- Ismertek a lépések előre? Akkor prompt chaining vagy routing, n8n vagy Zapier jellegű folyamatban, ahol minden lépés látható és naplózott.
- Csak a lépések paraméterei változnak, a sorrend nem? Akkor Plan Then Execute, a terv emberi vagy programozott jóváhagyásával.
- Valóban nyitott végű a feladat, és a hiba olcsón visszafordítható? Csak ekkor autonóm ügynök, sandboxban, limitekkel.
A tanácsadói gyakorlatban az automatizációs igények túlnyomó többsége a második lépésnél megáll. Az ügynök drágább, lassabb, nehezebben tesztelhető, és nagyobb a támadási felülete.
Az ügynök körüli védőkorlát lépésről lépésre
1. Eszközök jogosultsági szintekbe sorolva. Minden eszközhöz kategória tartozik.
| Szint | Példa | Szabály |
|---|---|---|
| read | Ügyfél keresése, dokumentum olvasása | Szabadon hívható, naplózva |
| write_reversible | Piszkozat létrehozása, címke hozzáadása | Hívható, visszavonható, naplózva |
| write_external | Email küldés, poszt publikálás, webhook | Emberi jóváhagyás a tényleges tartalom láttán |
| destructive | Törlés, fizetés, jogosultság módosítás | Ügynökből nem érhető el, vagy kétlépcsős jóváhagyás |
2. Legkisebb jogosultság. Eszközönként külön token, a felhasználó saját jogával. Nincs service_role, nincs admin API kulcs az ügynök kontextusában. A fájlrendszert egy munkakönyvtárra, a hálózatot allowlistre szűkítjük.
3. Sandbox. Kódot futtató ügynök konténerben vagy microVM-ben fut, alapból tiltott kimenő hálózattal, csak olvasható gyökérrel, idő és memória limittel. Titok nincs a sandbox környezeti változói között.
4. Költség és lépéslimit. Maximális lépésszám, maximális token, maximális időtartam, maximális költség munkamenetenként és felhasználónként naponta.
5. Idempotens eszközök. Minden író eszköz idempotencia kulcsot fogad. Ha az ügynök újrapróbál (hálózati hiba, timeout, modell ismétlés), a második hívás nem küld második emailt és nem vesz fel második számlát.
6. Audit napló. Minden tool hívás bekerül egy csak hozzáfűzhető táblába. Ki (felhasználó, ügynök, munkamenet), mit (eszköz, paraméterek maszkolva), mikor, milyen eredménnyel, ki hagyta jóvá.
Kódminta. Ügynök hurok a Claude API-val, minden korláttal
import Anthropic from "@anthropic-ai/sdk";
import { z } from "zod";
import { randomUUID } from "node:crypto";
const anthropic = new Anthropic();
const MODEL = process.env.LLM_MODEL_ID!; // a modell ID konfigurációból, nem a kódba égetve
type Tier = "read" | "write_reversible" | "write_external";
interface ToolDef<S extends z.ZodTypeAny> {
name: string;
description: string;
tier: Tier;
schema: S;
run: (input: z.infer<S>, ctx: Ctx) => Promise<unknown>;
}
interface Ctx { userId: string; sessionId: string; userToken: string }
const LIMITS = { maxSteps: 12, maxOutputTokens: 2_000, maxCostUsd: 0.5, maxMs: 120_000 };
const tools = [
{
name: "search_invoices",
description: "A felhasználó saját számlái között keres. Csak olvas.",
tier: "read",
schema: z.object({ partner: z.string().max(80), year: z.number().int().min(2020).max(2030) }).strict(),
run: async (i, ctx) => db(ctx.userToken).searchInvoices(i),
},
{
name: "draft_reminder_email",
description: "Fizetési emlékeztető PISZKOZATOT hoz létre. Nem küld el semmit.",
tier: "write_reversible",
schema: z.object({ invoiceId: z.string().uuid(), tone: z.enum(["udvarias", "hatarozott"]) }).strict(),
run: async (i, ctx) => mail(ctx.userToken).createDraft(i, { idempotencyKey: `${ctx.sessionId}:${i.invoiceId}` }),
},
] satisfies ToolDef<any>[];
export async function runAgent(task: string, ctx: Ctx) {
const started = Date.now();
let costUsd = 0;
const messages: Anthropic.MessageParam[] = [{ role: "user", content: task }];
for (let step = 0; step < LIMITS.maxSteps; step++) {
if (await killSwitchOn()) throw new Error("Ügynök leállítva (kill switch)");
if (Date.now() - started > LIMITS.maxMs) throw new Error("Időlimit");
const res = await anthropic.messages.create({
model: MODEL,
max_tokens: LIMITS.maxOutputTokens,
system: "Számlakezelő asszisztens. Csak a megadott eszközöket használd. Ha bizonytalan vagy, kérdezz.",
tools: tools.map(t => ({
name: t.name,
description: t.description,
input_schema: z.toJSONSchema(t.schema) as Anthropic.Tool.InputSchema,
})),
messages,
});
costUsd += estimateCost(res.usage);
if (costUsd > LIMITS.maxCostUsd) throw new Error("Költségkeret elfogyott");
messages.push({ role: "assistant", content: res.content });
if (res.stop_reason !== "tool_use") return res; // kész
const results: Anthropic.ToolResultBlockParam[] = [];
for (const block of res.content) {
if (block.type !== "tool_use") continue;
const tool = tools.find(t => t.name === block.name);
const callId = randomUUID();
if (!tool) {
results.push({ type: "tool_result", tool_use_id: block.id, is_error: true, content: "Ismeretlen eszköz" });
continue;
}
const parsed = tool.schema.safeParse(block.input);
if (!parsed.success) {
results.push({ type: "tool_result", tool_use_id: block.id, is_error: true,
content: `Érvénytelen paraméter: ${parsed.error.issues.map(i => i.path.join(".")).join(", ")}` });
continue;
}
if (tool.tier === "write_external") {
const ok = await requestApproval({ ctx, tool: tool.name, input: parsed.data, callId });
if (!ok) {
results.push({ type: "tool_result", tool_use_id: block.id, is_error: true, content: "A felhasználó elutasította" });
continue;
}
}
try {
const out = await tool.run(parsed.data, ctx);
await audit({ callId, ctx, tool: tool.name, input: mask(parsed.data), ok: true });
results.push({ type: "tool_result", tool_use_id: block.id, content: JSON.stringify(out).slice(0, 20_000) });
} catch (e) {
await audit({ callId, ctx, tool: tool.name, input: mask(parsed.data), ok: false });
results.push({ type: "tool_result", tool_use_id: block.id, is_error: true, content: "Az eszköz hibát adott" });
}
}
messages.push({ role: "user", content: results });
}
throw new Error("Lépéslimit elérve, emberi beavatkozás kell");
}
A minta kulcselemei.
- A Zod séma
.strict(), így ismeretlen mező nem csúszik át. - Az eszközválasz mérete vágva van, mert a nagy tool kimenet egyszerre költség és injekciós felület.
- A modellnek adott hibaüzenet rövid és belső részletek nélküli.
- A modell ID környezeti változóból jön, mert a modellnevek gyorsan változnak.
- A jóváhagyás a kódban van, nem a promptban.
-- Audit napló Supabase-ben: csak hozzáfűzhető, a felhasználó a sajátját látja
create table public.agent_audit (
id uuid primary key default gen_random_uuid(),
call_id uuid not null,
session_id uuid not null,
user_id uuid not null references auth.users(id),
tool text not null,
input_masked jsonb not null,
ok boolean not null,
approved_by uuid,
created_at timestamptz not null default now()
);
alter table public.agent_audit enable row level security;
create policy "own audit read" on public.agent_audit for select using (user_id = auth.uid());
-- insert csak szerver oldali függvényből, update és delete senkinek
revoke update, delete on public.agent_audit from anon, authenticated;
Emberi jóváhagyás jól megcsinálva
- A jóváhagyó felület a tényleges hatást mutatja. Címzett, teljes szöveg, összeg, érintett rekordok száma. Nem a modell saját összefoglalója.
- A jóváhagyás a konkrét paraméterekhez kötött. Hash-elve tároljuk, és végrehajtáskor újraszámoljuk. Ha a paraméter megváltozott, új jóváhagyás kell.
- Nincs mindent jóváhagyok gomb egy munkamenetre. Ez a jóváhagyási fáradtság, ami az ASI09 forrása.
- Kevés, de érdemi jóváhagyás. Ha minden olvasásra kérdezünk, a felhasználó gépiesen kattint. Ezért kell a fenti szintezés.
LLM kimenet strukturálása, validálása és a hallucináció kezelése
Strukturált kimenet lépésről lépésre
- Séma először. A kimenet formáját Zod sémában írjuk le, ebből generáljuk a JSON Schemát a modellnek és ebből validálunk.
- A modellt a sémára kényszerítjük. Tool use támogatású API-knál (például a Claude API-nál) erre egy kötelezően hívandó eszköz a bevált út (
tool_choicea konkrét eszközre), vagy a szolgáltató strukturált kimenet funkciója, ha elérhető a használt modellhez. - Validálás minden esetben. A kényszerített kimenetet is validáljuk, mert a séma szintaktikai, az üzleti szabály (például hogy a dátum ne legyen a múltban) nem fér bele.
- Hiba esetén egy javító kör. A validációs hibát visszaküldjük a modellnek, legfeljebb egyszer vagy kétszer. Utána determinisztikus hiba következik, nem végtelen ciklus.
- Szűk típusok. Enum szabad szöveg helyett, számtartomány, regex, maximális hossz. Minden szabad szöveges mező injekciós és hallucinációs felület.
const Triage = z.object({
category: z.enum(["ajanlatkeres", "szamla", "panasz", "egyeb"]),
urgency: z.enum(["alacsony", "normal", "surgos"]),
customerId: z.string().uuid().nullable(),
summary: z.string().max(280),
}).strict();
export async function triageEmail(emailText: string) {
const tool = { name: "record_triage", description: "Rögzíti az email besorolását.",
input_schema: z.toJSONSchema(Triage) as Anthropic.Tool.InputSchema };
for (let attempt = 0; attempt < 2; attempt++) {
const res = await anthropic.messages.create({
model: MODEL_SMALL, max_tokens: 500, tools: [tool],
tool_choice: { type: "tool", name: "record_triage" },
messages: [{ role: "user", content: `<email>\n${emailText}\n</email>` }],
});
const call = res.content.find(b => b.type === "tool_use");
const parsed = Triage.safeParse(call?.type === "tool_use" ? call.input : null);
if (parsed.success) {
// Üzleti ellenőrzés: a customerId létezik-e és a felhasználóé-e
if (parsed.data.customerId && !(await customerBelongsToUser(parsed.data.customerId))) {
return { ...parsed.data, customerId: null };
}
return parsed.data;
}
}
return { category: "egyeb", urgency: "normal", customerId: null, summary: "Kézi besorolás szükséges" } as const;
}
A customerBelongsToUser sor a minta lényege. Még a modell által adott azonosító is megbízhatatlan adat, a jogosultságot a kód ellenőrzi.
Hallucináció kezelése
| Technika | Hogyan | Mit véd ki |
|---|---|---|
| Grounding forrásazonosítóval | A válasz minden állítása mellé chunk ID, a kód ellenőrzi, hogy az ID a visszakeresett halmazban van | Kitalált hivatkozás |
| Idézet ellenőrzés | A modell szó szerinti idézetet ad, a kód megkeresi a forrásszövegben | Torzított forrás |
| Bizonytalanság engedélyezése | A sémában "nem_tudom" érték, a promptban kifejezett engedély | Kényszerített magabiztosság |
| Programozott ellenőrzés | Létező függvény, csomag, URL, adószám ellenőrzése a valós forrásban | Kitalált entitás |
| Kisebb feladat | Egy hívás egy kérdésre válaszol | Hosszú láncban felhalmozódó hiba |
| Ember a magas tétnél | Jogi, pénzügyi, egészségügyi kimenet emberi ellenőrzéssel | Az ASI09 típusú vak elfogadás |
RAG biztonság és multi tenant vektor adatbázis
Az alapszabály
A jogosultság a retrieval szintjén dől el, nem a promptban. Ha egy chunk bekerül a kontextusba, a modell kiírhatja. A szűrés ezért a lekérdezés dolga, a felhasználó azonosítója alapján, amit a szerver a tokenből olvas ki, nem a klienstől vagy a modelltől kap. Az RLS és a jogosultsági modell adatbázis oldali alapjairól az Adat és adatbázisok kézikönyv szól részletesen.
Lépésről lépésre Supabase és pgvector esetén
- Minden chunk sor hordozza a bérlőt és a jogosultsági kulcsot (
tenant_id,document_id, szükség eseténacltömb vagy csoport azonosító). - RLS a chunk táblán, ugyanazzal a szabállyal, mint a forrásdokumentum táblán. A dokumentum szintű ACL öröklődik a chunkra.
- A keresőfüggvény
security invoker, így az RLS a hívó felhasználó jogával fut.security definerfüggvényt keresésre nem használunk. - A hívás a felhasználó JWT-jével történik, nem
service_rolekulccsal. - Törlés és jogosultság visszavonás azonnal hat a chunkokra is (foreign key
on delete cascade, ACL változásnál újraindexelés vagy join a dokumentum táblára). - Indexelés előtt a dokumentum forrását és feltöltőjét rögzítjük, a nem megbízható forrásból származó chunkot megjelöljük (LLM05 és ASI06 ellen).
create table public.doc_chunks (
id bigserial primary key,
tenant_id uuid not null,
document_id uuid not null references public.documents(id) on delete cascade,
content text not null,
embedding vector(1024) not null,
source_trust text not null check (source_trust in ('internal','external')),
created_at timestamptz default now()
);
alter table public.doc_chunks enable row level security;
-- A felhasználó csak azokat a chunkokat látja, amelyek dokumentumához joga van
create policy "chunk via document acl" on public.doc_chunks for select
using (
exists (
select 1 from public.document_access da
where da.document_id = doc_chunks.document_id
and da.user_id = auth.uid()
)
);
create or replace function public.match_chunks(query_embedding vector(1024), match_count int default 8)
returns table (id bigint, document_id uuid, content text, similarity float)
language sql stable security invoker -- RLS a hívó jogával
as $$
select c.id, c.document_id, c.content, 1 - (c.embedding <=> query_embedding) as similarity
from public.doc_chunks c
order by c.embedding <=> query_embedding
limit least(match_count, 20);
$$;
Approximate indexeknél (HNSW, IVFFlat) ha az RLS szűrés a vektorindex után fut, egy erősen szűrt felhasználó kevesebb találatot kaphat a kértnél. Ilyenkor a hnsw.ef_search emelése, bérlőnkénti partícionálás vagy nagyobb bérlőnél külön index a megoldás, nem az RLS kikapcsolása.
Multi tenant elválasztás opciói
| Modell | Mikor | Kockázat |
|---|---|---|
Közös tábla, tenant_id és RLS | Sok kis bérlő, Supabase alapértelmezés | Egy rossz policy mindenkit kitesz, ezért policy teszt kell |
| Bérlőnkénti séma vagy namespace (Pinecone namespace, Qdrant collection) | Közepes számú bérlő, eltérő méret | A namespace nevet a kódnak kell a tokenből kiolvasnia, nem a kérésből |
| Bérlőnkénti adatbázis vagy projekt | Szabályozott ügyfél, szerződéses elvárás, EU adatrezidencia ügyfélenként | Üzemeltetési teher |
Külső vektor adatbázisnál (Pinecone, Qdrant, Weaviate) nincs RLS. Ott a szűrő metaadatot a szerver kód teszi a lekérdezésbe, kötelezően, egy wrapper függvényben, amit a többi kód nem kerülhet meg.
// Külső vektor DB: a tenant szűrő nem opcionális paraméter, hanem a wrapper része
export function vectorSearchFor(user: AuthedUser) {
return async (embedding: number[], topK = 8) =>
qdrant.search("chunks", {
vector: embedding,
limit: Math.min(topK, 20),
filter: { must: [
{ key: "tenant_id", match: { value: user.tenantId } }, // tokenből
{ key: "allowed_groups", match: { any: user.groupIds } }, // dokumentum ACL
] },
});
}
Tipikus hiba. A keresés service_role kulccsal fut egy edge functionben, és a szűrés a promptban történik (például azzal az utasítással, hogy a modell csak a felhasználó saját dokumentumai alapján válaszoljon). Ez nem szűrés.
Evaluáció
Miért kell
Az LLM alapú funkció viselkedése modellváltáskor, promptmódosításkor és adatváltozáskor csendben megváltozik. Eval készlet nélkül nem tudjuk, hogy egy változtatás javított vagy rontott.
Eval készlet építése lépésről lépésre
- Valós bemenetekből indulunk. 30 és 100 közötti, anonimizált valós eset a célközegből (emailek, kérdések, dokumentumok). Kitalált példák csak kiegészítésnek.
- Kategóriák szerint rétegzünk. Gyakori eset, határeset, rossz bemenet, támadó bemenet (prompt injekció a dokumentumban), olyan kérdés, amire a helyes válasz a nem tudom.
- Minden esethez elvárt kimenet vagy ellenőrző szabály tartozik. Ahol lehet, determinisztikus ellenőrzés (pontos egyezés, enum, regex, séma, tartalmazza vagy nem tartalmazza). LLM bíró csak ott, ahol a kimenet szabad szöveg.
- Biztonsági esetek külön csoportban. Ezeknél a küszöb 100 százalék. Ha egy injekciós eset átmegy, az kiadást blokkoló hiba.
- Verziózott, a repóban él (
evals/cases.jsonl), és minden promptváltozás, modellváltás, retrieval módosítás után fut. - Regressziós eval. Minden élesben talált hiba új esetté válik. Így a hiba nem jöhet vissza észrevétlenül.
// evals/run.ts: egyszerű, determinisztikus első réteg
interface Case { id: string; input: string; expect: { category?: string; mustNotContain?: string[] }; security?: boolean }
const cases: Case[] = readJsonl("evals/cases.jsonl");
let fail = 0, secFail = 0;
for (const c of cases) {
const out = await triageEmail(c.input);
const okCat = !c.expect.category || out.category === c.expect.category;
const okLeak = !(c.expect.mustNotContain ?? []).some(s => JSON.stringify(out).includes(s));
if (!(okCat && okLeak)) { fail++; if (c.security) secFail++; console.log("FAIL", c.id); }
}
console.log(`pass rate ${(100 * (cases.length - fail) / cases.length).toFixed(1)}%`);
if (secFail > 0 || fail / cases.length > 0.1) process.exit(1); // CI kapu
LLM as judge csapdái
| Csapda | Mi történik | Ellenszer |
|---|---|---|
| Pozíció torzítás | Párosított összevetésben a bíró az első vagy a második választ preferálja | Mindkét sorrendben futtatjuk, csak egyező ítélet számít |
| Hossz torzítás | A hosszabb választ jobbnak ítéli | Rubrikában kifejezett szempont, hossz normalizálás |
| Önpreferencia | Ugyanaz a modellcsalád a saját stílusát jutalmazza | Más család bírónak, vagy emberi minta kalibrálás |
| Homályos rubrika | 1 és 10 közötti pontszám jelentés nélkül | Bináris, konkrét kérdések (tartalmaz-e forrásazonosítót, van-e kitalált adat) |
| Kalibrálatlanság | Senki nem nézte meg, egyezik-e az emberrel | 30 és 50 közötti esetet ember is pontoz, mérjük az egyezést |
| Injekció a bíró ellen | A vizsgált kimenet utasítja a bírót | A kimenet címkézve, a bíró nem hív eszközt, az ítélet sémára kényszerítve |
| Ugyanaz a hiba | A bíró ugyanazt a tényt hallucinálja, mint a vizsgált modell | Ténykérdésnél determinisztikus ellenőrzés a forrásban |
Keretrendszerek és szabályozás
NIST AI RMF és a GenAI profil
- NIST AI RMF 1.0 (AI 100-1, 2023. január). Négy funkció. Govern (felelősség, szabályzat, kultúra), Map (kontextus és kockázatok feltárása), Measure (mérés, tesztelés), Manage (kezelés, prioritás, reagálás). Önkéntes, de az ügyfelek és az auditorok közös nyelve.
- NIST AI 600-1, Generative AI Profile (2024. július 26.). A GenAI sajátos kockázatai (konfabuláció, adatvédelem, információbiztonság, értéklánc és komponens integráció, káros tartalom, szellemi tulajdon és mások), a négy funkcióhoz rendelt javasolt intézkedésekkel. Ügyfél kockázatelemzéshez jó vázlat.
- NIST IR 8596, Cyber AI Profile. Előzetes tervezet 2025 decemberéből, a CSF 2.0 szerkezetére építve. Három fókusza az AI rendszerek védelme, az AI alapú védekezés és az AI alapú támadások elhárítása. A 2026 októberi állapot szerint még nem végleges.
- Az AI RMF 1.0 felülvizsgálata folyamatban van. Végleges új verzió 2026 októberében nincs, ellenőrizendő.
ISO/IEC 42001:2023
AI irányítási rendszer (AIMS) tanúsítható szabvány, az ISO 27001 logikájával (Plan Do Check Act, kockázatértékelés, Statement of Applicability, A melléklet kontrolljai). Akkor számít, ha az ügyfél nagyvállalat vagy szabályozott szektor, és beszállítói elvárásként jelenik meg. Kisebb szervezetnél a teljes tanúsítás ritkán indokolt, de a kontrollkatalógus jó ellenőrzőlista (AI rendszer leltár, hatásvizsgálat, adatminőség, harmadik fél kezelése). A szabványcsalád részletei az AI ISO szabványok, a tanúsítási folyamat az ISO megfelelés és audit kézikönyvben szerepelnek.
EU AI Act. Kötelezettségek és határidők a Digital Omnibus után
Az AI Act (EU 2024/1689) 2024. augusztus 1-jén lépett hatályba. A Digital Omnibus on AI (EU 2026/1744) a 2026 októberi állapot szerint 2026. július 24-én jelent meg a Hivatalos Lapban, és július 27-én lépett hatályba. Ez módosította a magas kockázatú rendszerek határidejét. A dátumokat ügyfélanyagban az eur-lex.europa.eu aktuális szövegével érdemes összevetni.
| Időpont | Mi lép életbe |
|---|---|
| 2025. február 2. | Tiltott gyakorlatok (5. cikk), AI jártasság (4. cikk) |
| 2025. augusztus 2. | Általános célú AI modellek (GPAI) szolgáltatói kötelezettségei, irányítás, szankciók |
| 2026. augusztus 2. | Átláthatósági kötelezettségek (50. cikk) általános alkalmazása, ezt az Omnibus nem halasztotta |
| 2026. december 2. | Új tilalmak (beleegyezés nélküli intim képek generálása, CSAM), türelmi idő vége az 50. cikk (2) gépi jelölésére a 2026. augusztus 2. előtt forgalomba hozott rendszereknél |
| 2027. december 2. | III. melléklet szerinti magas kockázatú rendszerek (foglalkoztatás, oktatás, hitelbírálat, alapvető szolgáltatások), eredetileg 2026. augusztus 2. |
| 2028. augusztus 2. | I. melléklet szerinti, szabályozott termékbe épített magas kockázatú rendszerek |
Kockázati szintenként, fejlesztői (provider) szemmel.
| Szint | Példa a gyakorlatból | Kötelezettség |
|---|---|---|
| Tiltott | Munkahelyi érzelemfelismerés, manipulatív technika | Nem építjük meg |
| Magas kockázat | Önéletrajz szűrő, teljesítményértékelő, hitelbírálati segéd | Kockázatkezelési rendszer, adatminőség, műszaki dokumentáció, naplózás, átláthatóság a deployer felé, emberi felügyelet, pontosság és robusztusság, megfelelőségértékelés, regisztráció, forgalomba hozatal utáni monitorozás |
| Átláthatósági kötelezettség | Chatbot, szintetikus tartalom generálás, deepfake | Az ember tudja, hogy AI-val beszél, a generált tartalom gépileg jelölt, a deepfake jelölt |
| Minimális | Belső szövegösszefoglaló, kódasszisztens | Nincs külön kötelezettség, az AI jártasság és a GDPR érvényes |
Gyakorlati következmény. Egy ügyfélnek épített chatbot már most az 50. cikk alá esik, tehát a felületen jelezni kell, hogy a felhasználó AI-val beszél. HR célú szűrő ügynök magas kockázatú, ott 2027 decemberétől a teljes kötelezettségcsomag él, és a dokumentációt (adat, teszt, emberi felügyelet) már a fejlesztéskor érdemes gyűjteni. Aki egy kész GPAI modellt jelentősen nem módosít, nem válik GPAI szolgáltatóvá. Mindez szakmai értelmezés, nem jogi tanács, határesetben ügyvédi vélemény kell. A szervezeti oldalról az Irányítási rendszerek és governance kézikönyv szól.
MITRE ATLAS
Az ATT&CK mintájára épülő tudásbázis az AI rendszerek elleni támadási taktikákról, technikákról és valós esettanulmányokról. 16 taktikája van, a technikák száma évente nő, 2025 és 2026 folyamán jelentős ügynöki tartalommal bővült (kontextus és memória mérgezés, ügynök konfiguráció manipulálása, kiszivárogtatás tool hívással, ügynöki eszköz hitelesítő adatainak megszerzése). Red team tervezéshez és fenyegetési modellezéshez használjuk. A pontos számokat az aktuális kiadásban érdemes ellenőrizni, mert a másodlagos források ellentmondanak egymásnak.
Hogyan kapcsolódnak egymáshoz
| Kérdés | Forrás |
|---|---|
| Milyen sérülékenységek vannak egy LLM alkalmazásban | OWASP LLM Top 10 |
| Mi romolhat el egy ügynöknél | OWASP Agentic Top 10 |
| MCP szerver bekötése | OWASP MCP Top 10 és az MCP spec Security Best Practices |
| Hogyan támad egy valós támadó | MITRE ATLAS |
| Hogyan szervezzük a kockázatkezelést | NIST AI RMF és AI 600-1 |
| Mit kell tanúsítani | ISO/IEC 42001 |
| Mi a jogi kötelezettség | EU AI Act és GDPR |
A GDPR és az adatkezelési oldal az Adatbiztonság és adatvédelem, az általános támadási felület a Kiberbiztonság kézikönyvben kap részletes tárgyalást.
A vibecoding fogalma és a felelős változat
Karpathy eredeti meghatározása (2025. február 2.)
Andrej Karpathy egy X bejegyzésben nevezte el. Olyan kódolási mód, ahol az ember átadja magát a hangulatnak, a kódot nem olvassa, a diffet nem nézi, a hibaüzenetet megjegyzés nélkül visszamásolja a modellnek, és ha valami nem megy, addig kér változtatást, amíg működni nem kezd. Karpathy maga hétvégi, eldobható projektekre szánta. A kifejezés a Collins szótár 2025-ös szava lett, és közben jelentése kitágult, a köznyelvben ma már szinte minden AI asszisztált fejlesztést így hívnak.
2026 februárjában Karpathy az egy évvel korábbi bejegyzését egy gyors ötletnek nevezte, és a professzionális AI asszisztált munkára új nevet javasolt, agentic engineering. A gondolat lényege, hogy a fejlesztő az idő túlnyomó részében már nem maga írja a kódot, hanem ügynököket irányít és felügyel, és ez tanulható, mérnöki szakértelem.
A két mód szétválasztása
| Szempont | Vibecoding (eredeti értelem) | Felelős AI asszisztált fejlesztés |
|---|---|---|
| Cél | Gyors prototípus, kísérlet, saját eszköz | Ügyfélnek, élesbe, adatot kezelő rendszer |
| Kód olvasása | Nem | Minden diff átnézve, a kockázatos részek soronként |
| Specifikáció | Fejben | Írott, a repóban |
| Teszt | Kézi kattintgatás | Automatikus, a jogosultsági és hibaágakra is |
| Titok és adat | Mindegy, nincs valós adat | Valós adat csak ellenőrzött jogosultsággal |
| Ki dönt | A modell | Az ember dönt a szerkezetről, az adatról és a bizalmi határokról |
Vibecoding akkor rendben van, ha a kódot ki lehet dobni, és nem kezel más ember adatát. Amint egy prototípus valós felhasználót, valós adatot vagy pénzt kap, átlép a felelős módba, és a lent leírt munkarend érvényes rá. Ezt az átlépést tudatosan kimondjuk, mert a prototípusok csendben szoktak élessé válni.
Mit mondanak a kutatások
| Kutatás | Év | Fő megállapítás | Mire figyelmeztet |
|---|---|---|---|
| Perry, Srivastava, Kumar, Boneh (Stanford), Do Users Write More Insecure Code with AI Assistants? | 2022 preprint, ACM CCS 2023 | 47 résztvevős kísérlet, az AI asszisztenst használók szignifikánsan kevésbé biztonságos kódot írtak (különösen titkosításnál és SQL injekciónál), és közben inkább hitték, hogy biztonságos | A túlzott magabiztosság a fő kockázat. Aki kevésbé bízott a modellben és átfogalmazta a kérést, jobb kódot írt |
| Veracode, GenAI Code Security Report | 2025. július | 80 feladat, több mint 100 modell, a generált kód 45 százaléka tartalmazott OWASP Top 10 típusú sérülékenységet, választási helyzetben a modellek 45 százalékban a nem biztonságos utat választották, XSS ellen a kód 86 százaléka nem védett, a Java volt a legrosszabb nyelv | A nagyobb vagy újabb modell nem lett arányosan biztonságosabb. A 2026 tavaszi frissítés nagyjából 55 százalékos megfelelést mért |
| Spracklen és mtsai, We Have a Package for You! (USENIX Security 2025) | 2025 | 16 modell, 576 ezer kódminta, a hivatkozott csomagok közel 20 százaléka nem létezett, 205 474 egyedi kitalált név, nyílt modelleknél jóval magasabb arány, a kitalált nevek jelentős része ismétlődik | Ez teszi kihasználhatóvá a slopsquattingot. A támadó előre regisztrálja a gyakran hallucinált nevet |
| METR, randomizált kontrollált kísérlet tapasztalt open source fejlesztőkkel | 2025. július | 16 fejlesztő, 246 feladat saját, nagy kódbázisban, AI eszközzel 19 százalékkal lassabbak voltak, miközben azt hitték, 20 százalékkal gyorsabbak | Az érzett és a mért produktivitás eltérhet. Mérni kell, nem érezni |
| Lovable, CVE-2025-48757 | 2025 | 1645 nyilvános bemutató appból 170 esetén a Supabase táblák a publikus anon kulccsal olvashatók vagy írhatók voltak, mert hiányzott vagy hibás volt az RLS | A generált appok tipikus hibája a hiányzó RLS. Egy biztonsági szkenner, ami csak az RLS meglétét nézi, a hibás policyt nem találja meg |
A slopsquatting kifejezés Seth Larsontól (Python Software Foundation) származik, a typosquatting mintájára. Ismert eset egy kutató által üresen regisztrált, gyakran hallucinált huggingface-cli csomag, ami három hónap alatt több tízezer letöltést kapott.
Összességében az AI generált kód tipikusan működik, és alapból tipikusan nem biztonságos. A hibák nem véletlenszerűek, hanem visszatérő mintázatok, ezért katalogizálhatók és célzottan kereshetők.
AI generált kód tipikus hibái. Katalógus és felismerés
| # | Hiba | Hogyan néz ki | Hogyan találjuk meg | Javítás |
|---|---|---|---|---|
| 1 | Kikapcsolt vagy hiányzó RLS | create table RLS nélkül, using (true) policy, a hibát a modell RLS kikapcsolással oldotta meg | select tablename from pg_tables where schemaname='public' and not rowsecurity; és Supabase advisor | RLS minden public táblán, policy tulajdonos szerint, policy teszt két felhasználóval |
| 2 | Titok a kliensben | service_role, Stripe secret, OpenAI vagy Anthropic kulcs NEXT_PUBLIC_ vagy VITE_ előtaggal, kulcs a frontend kódban | grep a service_role, sk_live, sk-ant- mintákra és a KEY vagy SECRET végű publikus változókra (lásd az átvilágító szkriptet), gitleaks, a build kimenet átnézése | Titok csak szerver oldalon (edge function, API route), kulcsrotáció, ha már kiment |
| 3 | Hiányzó tulajdonos ellenőrzés (IDOR) | /api/invoice/[id] lekéri az ID alapján, nem nézi, kié | Minden ID paraméteres végpontnál keressük a user_id = auth.uid() vagy azzal egyenértékű feltételt | Tulajdonos szűrés a lekérdezésben vagy RLS, teszt idegen ID-val |
| 4 | Hallucinált API vagy csomag | Nem létező függvény, rossz paraméter, nem létező npm csomag | Típusellenőrzés (tsc --noEmit), npm view minden új függőségre, a dokumentáció megnyitása | A generált import mellé a hivatalos dokumentáció linkje, csomag csak ellenőrzött kiadótól |
| 5 | Túl sok függőség | Egy dátum formázáshoz moment, egy deep clone-hoz lodash, három UI könyvtár egyszerre | package.json diff átnézése, npx depcheck | Függőség csak indoklással, beépített API elsőként |
| 6 | Copy paste duplikáció | Ugyanaz a validáció öt fájlban, kissé eltérően | npx jscpd src/, hasonló nevű függvények keresése | Egy hely a szabálynak (Parnas elve), a modellnek megmondjuk, melyik modult használja |
| 7 | Elhagyott vagy elnyelt hibakezelés | catch (e) {}, catch { return null }, console.log(e) és tovább | grep az üres catch blokkokra (lásd az átvilágító szkriptet), ESLint no-empty | Hiba naplózva, a felhasználó felé értelmes üzenet, a hívó tudja, hogy hiba volt |
| 8 | Semmit nem ellenőrző teszt | expect(true).toBe(true), mindent mockol, a tesztet a modell a kódhoz igazította, ahelyett hogy a kódot javította volna | Mutációs teszt (Stryker), a teszt elrontott kóddal is zöld-e, assert nélküli tesztek keresése | Teszt a specifikációból, nem a kódból, legalább egy hibaág és egy jogosultsági ág tesztje |
| 9 | Kliens oldali jogosultság | Az admin gomb el van rejtve, de a végpont mindenkinek válaszol | Minden végpont meghívása curl-lel jogosultság nélkül | Szerver oldali ellenőrzés minden végponton |
| 10 | Nyitott CORS és hiányzó rate limit | Access-Control-Allow-Origin: * hitelesített végponton, LLM végpont limit nélkül | Fejlécek ellenőrzése, terheléses próba | Origin allowlist, felhasználónkénti limit, költségkeret |
| 11 | Validálatlan bemenet és kimenet | JSON.parse séma nélkül, az LLM kimenete egyből HTML-be | Zod vagy hasonló séma hiánya a bizalmi határon | Séma minden bizalmi határon, a strukturált kimenetnél leírtak szerint |
| 12 | Csendes viselkedésváltozás a javítás közben | A modell egy hiba javításakor törli a validációt vagy a tesztet, hogy zöld legyen | A diff törölt sorainak külön átnézése | Szabály a projekt AI kontextusfájljában, tesztet és validációt csak kifejezett kérésre lehet törölni |
| 13 | Elavult minta | Régi SDK hívás, elavult auth folyamat, régi MCP protokollverzió | Verzió összevetése a lockfile és a dokumentáció között | A projekt kontextusában rögzítjük a használt verziókat |
Gyors átvilágító szkript egy örökölt, vibecodinggal készült repóra
#!/usr/bin/env bash
# audit-vibe.sh: első kör, nem helyettesíti az emberi átnézést
set -u
echo "== Titkok a kódban =="
grep -rnE "service_role|sk_live_|sk-ant-|-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY" --include=*.{ts,tsx,js,jsx,env,json} . 2>/dev/null | grep -v node_modules
echo "== Publikus env változóban titok =="
grep -rnE "(NEXT_PUBLIC|VITE|EXPO_PUBLIC)_[A-Z_]*(SECRET|SERVICE|PRIVATE)" . 2>/dev/null | grep -v node_modules
echo "== Üres catch =="
grep -rnE "catch *(\([^)]*\))? *\{ *\}" --include=*.{ts,tsx,js} src 2>/dev/null
echo "== Assert nélküli vagy triviális teszt =="
grep -rnE "expect\(true\)|toBeTruthy\(\)\s*;?\s*$" --include=*.test.* . 2>/dev/null | grep -v node_modules
echo "== Duplikáció =="
npx -y jscpd@4 --min-lines 8 --silent src 2>/dev/null | tail -3
echo "== Függőségek =="
npx -y depcheck@1 2>/dev/null | head -20
echo "== RLS nélküli táblák (Supabase) =="
echo "select tablename from pg_tables where schemaname='public' and not rowsecurity;"
Slopsquatting elleni kapu
// scripts/check-new-deps.ts: CI-ban fut minden PR-en, ami package.json-t módosít
import { execSync } from "node:child_process";
const diff = execSync("git diff origin/main -- package.json").toString();
const added = [...diff.matchAll(/^\+\s+"([^"]+)":\s*"[^"]+"/gm)].map(m => m[1]);
for (const name of added) {
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name)}`);
if (res.status === 404) throw new Error(`Nem létező csomag: ${name} (hallucináció?)`);
const meta = await res.json();
const created = new Date(meta.time?.created);
const ageDays = (Date.now() - created.getTime()) / 86_400_000;
const dl = await fetch(`https://api.npmjs.org/downloads/point/last-week/${name}`).then(r => r.json());
if (ageDays < 90 || (dl.downloads ?? 0) < 1000) {
throw new Error(`Gyanús új csomag: ${name}, ${Math.round(ageDays)} napos, ${dl.downloads} heti letöltés. Emberi jóváhagyás kell.`);
}
}
A fiatal és alig letöltött csomag nem feltétlenül rossz, de emberi döntést igényel. Pythonra ugyanez a PyPI JSON API-val (https://pypi.org/pypi/{név}/json) írható meg.
A felelős AI asszisztált fejlesztés munkarendje
Specifikáció vezérelt fejlesztés (spec driven development)
A specifikáció az a dokumentum, amit a modell és az ember is olvas, és ami alapján a kód és a teszt készül. 2025 óta eszközök is épülnek rá (GitHub Spec Kit, Amazon Kiro, a Claude Code plan módja), de a módszer eszköz nélkül is működik.
Lépésről lépésre.
- Egy oldalas spec a repóban (például
docs/specs/alatt, funkciónként egy fájl). Cél egy bekezdésben, felhasználók és jogosultságok, adatmodell (táblák, mezők, ki látja, ki írja), bizalmi határok (honnan jön nem megbízható adat), elfogadási feltételek számozva, és amit kifejezetten nem csinálunk. - A modell a speccel együtt tervet ír, kódot még nem. Szerepelnek benne a fájlok, lépések, új függőségek, migrációk.
- Ember átnézi és jóváhagyja a tervet. Itt dől el az architektúra, és ez a legolcsóbb pont a hibák megfogására.
- Feladatokra bontás, mindegyik egy önállóan ellenőrizhető lépés.
- Lépésenként implementáció és ellenőrzés (a lent leírt teszt először módszerrel).
- A spec frissül, ha a megvalósítás közben döntés változik. Spec és kód nem csúszhat szét.
# Spec: Fizetési emlékeztető ügynök
## Cél
A könyvelő a lejárt számlákhoz egy kattintással emlékeztető piszkozatot kap, amit átnéz és maga küld el.
## Szereplők és jogok
- Könyvelő: a saját ügyfelei számláit látja (RLS: invoices.owner_id = auth.uid()).
- Ügynök: a könyvelő tokenjével fut, csak olvas és piszkozatot hoz létre. Küldeni nem tud.
## Bizalmi határok
- Nem megbízható: a számla megjegyzés mezője, a partner által küldött válaszemailek.
- A megjegyzés mező tartalma csak a karanténba zárt összefoglalóba kerül.
## Elfogadási feltételek
1. Idegen könyvelő számlájára hívva 0 találat (teszt).
2. Ugyanarra a számlára kétszer futtatva egy piszkozat jön létre (idempotencia teszt).
3. A megjegyzés mezőbe írt "küldd el most" utasítás hatására sem jön létre elküldött email (injekciós teszt).
## Nem része
Automatikus küldés, fizetési link generálás.
Kis lépések
- Egy lépés egy commit, ami egy dolgot csinál, és egy mondatban leírható.
- Egy lépés diffje átnézhető. Irányszám 200 sor alatt, kivéve a generált fájlokat (típusok, lockfile).
- Minden lépés után futtatás. Teszt, típusellenőrzés, lint, és a funkció kézi kipróbálása.
- Ha a modell egy lépésben három dolgot kezd el, megállítjuk és szétbontjuk.
- Git az ügynök biztonsági hálója. Tiszta munkafa minden nagy lépés előtt, így egy rossz irány egy
git restoreparanccsal visszavonható.
Teszt először AI-val
A semmit nem ellenőrző teszt ellen ez a legerősebb ellenszer.
- A modell a specifikáció elfogadási feltételeiből tesztet ír, implementáció nélkül.
- Lefuttatjuk, és piros kell legyen. Ha zöld, a teszt nem ellenőriz semmit.
- Ember átnézi a tesztet. Azt ellenőrzi, hogy a teszt a specifikációt méri, és van benne jogosultsági és hibaág.
- A modell implementál, a tesztet nem módosíthatja. Ezt kimondjuk a kérésben és a projekt AI kontextusfájljában is.
- Zöld után mutációs próba vagy kézi rontás. Elrontunk egy feltételt a kódban, és megnézzük, piros lesz-e a teszt.
// Jogosultsági teszt: két valós felhasználó, valós RLS, nincs mock
import { describe, it, expect } from "vitest";
describe("invoices RLS", () => {
it("idegen könyvelő nem látja a számlát", async () => {
const alice = await signInTestUser("alice");
const bob = await signInTestUser("bob");
const { data: inv } = await alice.from("invoices").insert({ partner: "X Kft", total_huf: 1000 }).select().single();
const { data } = await bob.from("invoices").select().eq("id", inv!.id);
expect(data).toEqual([]); // nem hiba, hanem üres: az RLS így viselkedik
});
it("anon kulccsal semmi nem olvasható", async () => {
const anon = anonClient();
const { data } = await anon.from("invoices").select();
expect(data ?? []).toHaveLength(0);
});
});
A kontextus kezelése
A modell annyit tud a projektről, amennyit a kontextusában lát. Jó kontextus kevés, pontos és naprakész.
| Eszköz | Mire való | Mi kerül bele |
|---|---|---|
| Projekt kontextusfájl a repó gyökerében (AGENTS.md, Claude Code esetén CLAUDE.md) | Állandó projekt szabályok, minden munkamenet elején betöltődik | Stack és verziók, parancsok (teszt, lint, migráció), architekturális szabályok, tiltások, hol mi van |
| Alkönyvtári kontextusfájl | Egy modulra vonatkozó szabály | Például a supabase/ alatt a migrációs és RLS szabályok |
docs/specs/, docs/adr/ | Döntések és specifikációk | Amire a kontextusfájl hivatkozik, nem bemásolva |
| Felhasználói szintű memória | Személyes, projektek közötti preferencia | Stílus, terminológia, munkamódszer |
| Újrahasználható utasításcsomag (skill, playbook) | Ismétlődő, összetett feladat módszertana | Munkarend, ellenőrzőlista, kódminták, ahogy ebben a kézikönyvben |
Szabályok a kontextushoz.
- A kontextusfájl legyen rövid, és csak olyat tartalmazzon, ami minden munkamenetben számít. Egy hosszú, mindent tartalmazó fájl elhalványítja a fontos szabályokat.
- Minden szabály ellenőrizhető mondat legyen (például migráció csak a
supabase/migrationsalá,service_rolekulcs kliens kódban tilos), ne általános jókívánság (például írj tiszta kódot). - Hosszú munkamenetben a kontextus telítődik, a modell elfelejti a korai döntéseket. Nagyobb feladatnál új munkamenet indul a spec és a terv fájlból.
- Más forrásból (weboldal, issue, harmadik fél README) beolvasott szöveg ugyanúgy nem megbízható tartalom a kódoló ügynök számára, mint egy futó ügynöknek. Egy repóba rejtett utasítás a kódoló asszisztenst is irányíthatja.
# AGENTS.md (részlet egy Supabase + Next.js ügyfélprojektből)
## Stack
Next.js 15 App Router, Supabase (Postgres 15, RLS), Anthropic SDK, Zod 4. MCP SDK protokoll: 2025-11-25.
## Parancsok
- Teszt: `npm test` | Típus: `npm run typecheck` | Lint: `npm run lint`
- Migráció: `supabase migration new <nev>`, soha nem kézi SQL az éles DB-n
## Kötelező
- Minden új public táblán RLS és legalább egy policy teszt két felhasználóval.
- Titok csak szerver oldalon. `NEXT_PUBLIC_` előtag csak publikus értékre.
- LLM kimenet Zod sémán megy át, mielőtt bárhová kerül.
- Új npm függőség csak indoklással a PR leírásában.
## Tilos kérés nélkül
- Teszt törlése vagy gyengítése, validáció eltávolítása, RLS kikapcsolása.
- `service_role` kulcs használata felhasználói kéréshez.
Review stratégia
A generált kódot nem egyenletes figyelemmel nézzük át, hanem a kockázat szerint osztjuk el a figyelmet.
| Szint | Mit nézünk | Hogyan |
|---|---|---|
| Mindig soronként | Jogosultság, RLS, auth, titok kezelés, pénz, törlés, LLM kimenet felhasználása, új függőség, migráció | Ember olvassa, kérdez, kipróbálja |
| Szerkezet szinten | Új modul, új végpont, adatmodell változás | A spec és az ADR alapján, a modul határok helyén vannak-e |
| Mintavétellel | UI komponens, stílus, szöveg | Futtatva és ránézve |
| Automatikusan | Formázás, lint, típus, duplikáció, ismert sérülékenység | CI (ESLint, tsc, gitleaks, npm audit vagy osv-scanner, Supabase advisor) |
Hasznos technikák.
- Második vélemény más kontextusból. Egy friss munkamenet vagy egy külön review ügynök nézi át a diffet, amely nem látta a generálás menetét, csak a specet és a diffet. A kódot író modell hajlamos igazolni a saját megoldását.
- A törölt sorok külön átnézése. A generált diffben a csendes törlés (validáció, teszt, ellenőrzés) a legveszélyesebb, és felette a legkönnyebb elsiklani.
- Rákérdezés a modell saját kódjára. Milyen bemenetre hibázik, mit feltételez a hívóról, mi történik, ha a felhasználó nincs bejelentkezve. A válaszokat ellenőrizzük, nem elfogadjuk.
Mikor kell embernek döntenie
Ezek a döntések nem delegálhatók a modellre. A modell javasolhat, de az ember mondja ki.
- Adatmodell és jogosultsági modell (ki mit lát és módosít).
- Bizalmi határok és hogy mely adat kerülhet LLM szolgáltatóhoz (GDPR, DPA, adatrezidencia).
- Új külső szolgáltató, új függőség, új MCP szerver bekötése.
- Visszafordíthatatlan művelet éles rendszeren (migráció adatvesztéssel, törlés, kulcsrotáció, deploy).
- Ügynök önállóságának mértéke (mely eszköz igényel jóváhagyást).
- Biztonsági kompromisszum (például egy ellenőrzés elhagyása határidő miatt). Ezt írásban rögzítjük.
- Az, hogy egy prototípus élessé válik-e.
A gyakorlatban
Szabályok minden AI, ügynök és MCP feladatnál
- Az LLM kimenet és minden külső tartalom nem megbízható adat. A kódban mindig séma validáción és escape-en megy át, mielőtt HTML-be, SQL-be, shellbe, fájlútba, URL-be vagy egy másik eszköz paraméterébe kerül.
- Biztonsági szabály a kódba kerül, nem a promptba. Ha egy követelmény úgy szól, hogy az ügynök ne tegyen valamit, a csapat megkeresi hozzá a determinisztikus kényszert (eszköz eltávolítása, jogosultság szűkítése, jóváhagyási kapu), és azt építi meg.
- Workflow az alapértelmezés. Autonóm ügynököt csak akkor javaslunk, ha a workflow döntési sorrend negyedik lépéséig eljutottunk, és ezt írásban indokoljuk.
- A lethal trifecta ellenőrzése minden ügynök tervnél. Ha a három képesség egy munkamenetben jóváhagyás nélkül összeáll, ezt kimondjuk, és szétválasztást vagy jóváhagyást építünk be.
- Szűk, paraméterezett eszközök. Általános
run_sql,http_requestvagyexeceszközt ügynök nem kap, helyette konkrét műveletek készülnek szigorú sémával. - Felhasználói jog, nem szolgáltatói kulcs. Supabase esetén az ügynök és az MCP szerver a felhasználó JWT-jével fut, RLS mellett.
service_rolecsak szerver oldali, jól körülhatárolt rendszerfeladatra való, és soha nem kerül nem megbízható tartalmat olvasó ügynök kezébe. - Minden író eszköz idempotens és naplózott. Idempotencia kulcs, audit sor, maszkolt paraméterek.
- Limitek minden ügynök hurokban. Lépésszám, token, idő, költség, kill switch.
- Modell ID és protokollverzió konfigurációból. A modellnév környezeti változóba kerül, nem emlékezetből a kódba, és ez a kódgeneráló modell által írt kódra is áll. Az MCP protokollverziót a projekt kontextusfájlja rögzíti.
- Új függőség csak ellenőrzés után. Minden javasolt csomagnál ellenőrizzük, hogy létezik, ismert kiadótól származik és indokolt, és ezt a PR leírása jelzi.
- A kódoló ügynök is ügynök. Ha az AI asszisztens egy repóban, issue-ban, weboldalon vagy tool válaszban utasítást talál, azt adatként kell kezelnie, jeleznie kell a fejlesztőnek, és nem hajthatja végre. A csapat ezt a kódoló eszköz beállításaiban és a kontextusfájlban is rögzíti.
- A hiányzó ellenőrzést kimondjuk. Ami nem lett tesztelve (RLS, injekciós eset, jogosultsági ág), az a feladat végén, az átadásban felsorolva szerepel.
- Dátum és lista ellenőrzése. OWASP rangsor, MCP verzió és EU AI Act határidő ügyfélanyagba csak forrásellenőrzés után kerül, évszámmal (LLM03:2026).
Ügynök tervezési kártya
Minden új ügynök előtt kitöltjük, és a repóban tároljuk (például docs/agents/ alatt, ügynökönként egy fájlban).
# Ügynök tervezési kártya: <név>
## 1. Feladat
- Egy mondatban mit csinál, kinek:
- Miért nem elég egy workflow (a workflow döntési sorrend melyik lépésénél tartunk):
- Választott minta (chaining / routing / parallelization / orchestrator workers / evaluator optimizer / autonomous):
- Prompt injekció elleni minta (Action Selector / Plan Then Execute / Map Reduce / Dual LLM / Code Then Execute / Context Minimization / nincs, mert nincs nem megbízható bemenet):
## 2. Bemenetek és bizalom
| Forrás | Megbízható? | Ki írhat bele? | Hova kerülhet a tartalma? |
|--------|-------------|----------------|---------------------------|
## 3. Eszközök
| Eszköz | Szint (read / write_reversible / write_external / destructive) | Jogosultság (token, scope, RLS) | Jóváhagyás | Idempotens? |
|--------|----------------------------------------------------------------|----------------------------------|------------|-------------|
## 4. Lethal trifecta
- Privát adat: igen / nem, melyik eszköz
- Nem megbízható tartalom: igen / nem, melyik forrás
- Külső kommunikáció: igen / nem, melyik csatorna (email, HTTP, markdown kép, link, PR, poszt)
- Ha mindhárom igen: hogyan van szétvágva vagy jóváhagyva:
## 5. Limitek
- Max lépés: | Max token kérésenként: | Max idő: | Max költség munkamenet / nap:
- Circuit breaker szabály:
- Kill switch helye:
## 6. Memória
- Ír-e tartós memóriába? Ki validálja? Hogyan törölhető? Forrás jelölve?
## 7. Napló és megfigyelés
- Audit tábla, megőrzési idő, PII maszkolás, riasztás mire:
## 8. Eval
- Eval készlet helye, esetek száma, biztonsági esetek száma (küszöb 100%):
- Ki kalibrálta az LLM bírót, ha van:
## 9. Szabályozás
- EU AI Act szint (tiltott / magas / átláthatósági / minimális), indoklás:
- Személyes adat megy-e LLM szolgáltatóhoz? DPA, régió, tanítási kizárás:
## 10. Döntéshozó
- Ki hagyta jóvá a kártyát, dátum:
MCP szerver bekötési checklist
Harmadik fél MCP szerverének bekötése előtt, legyen szó asztali AI kliensről, kódoló asszisztensről vagy saját kliensről.
- Forrás. Ismert kiadó, aktív karbantartás, nyílt forráskód vagy hivatalos szolgáltatói szerver. Nem egy ismeretlen fork.
- Verzió rögzítve.
[email protected]vagy konténer image digest, nemlatest. Lockfile a repóban. - Teljes indító parancs elolvasva. Nincs benne
curl | sh,sudo, rejtett második parancs. - A
tools/listteljes válasza elolvasva. Nincs utasító szöveg a leírásokban, nincs rejtett karakter, nincs a feladathoz nem illő paraméter (notes, context, sidenote). - Tool leírás hash rögzítve, változás esetén a kliens nem indul vagy figyelmeztet (rug pull ellen).
- Jogosultság. A szerver a lehető legszűkebb tokennel fut, csak olvasó, ha a feladat engedi. Supabase MCP-nél fejlesztői projekt, read only mód, project scoping, soha éles adat
service_rolejoggal. - Távoli szervernél. OAuth 2.1 PKCE-vel, a token audience a szerverre szól, a szerver nem adja tovább a tokenünket (token passthrough), HTTPS, a beleegyezés képernyő a valós scope-okat mutatja.
- Helyi szervernél. Sandbox vagy konténer, korlátozott fájlrendszer (csak a munkakönyvtár), korlátozott kimenő hálózat. Ha HTTP-n hallgat helyben, tokennel védett.
- Lethal trifecta. A munkamenetben a többi bekötött szerverrel együtt nem áll-e össze a három képesség. Egy email olvasó és egy webes fetch szerver együtt már kettő, egy privát adatbázis a harmadik.
- Szerverek száma minimális. Csak a feladathoz szükséges szerverek aktívak a munkamenetben.
- Jóváhagyási beállítás. Író és külső kommunikációs eszközök kliens oldali jóváhagyással, nem automatikus engedéllyel.
- Naplózás. A tool hívások visszakereshetők.
- Leltár. A szerver felkerül a szervezet MCP leltárába (shadow MCP ellen), gazdával és felülvizsgálati dátummal.
Saját MCP szerver írásakor ezen felül a következők teljesülnek.
- Szűk, paraméterezett eszközök Zod sémával, nincs általános SQL vagy shell.
- Annotációk kitöltve (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint), de a szerver nem támaszkodik rájuk. - Audience és issuer ellenőrzés minden kérésnél, a downstream felé saját token.
- Állapot handle véletlen, lejáró, a hitelesített felhasználóhoz kötve.
- Hibaüzenetben nincs stack trace, belső út, titok.
- Tool válasz mérete korlátozott, a nem megbízható tartalom jelölve a válaszban.
- Shell hívás csak argumentum tömbbel,
shell: false, allowlistelt paranccsal. - Tesztek két felhasználóval (bérlők közti szivárgás), injekciós tesztek a tool leírásra és a tool válaszra.
LLM végpont deploy előtti kapu
Minden LLM-et hívó végpont, edge function, n8n vagy Zapier lépés élesítése előtt. Ha egy pont nem teljesül, nem deployolunk, vagy a hiányt írásban vállaljuk.
Bemenet és jogosultság
- A végpont hitelesít, a felhasználó azonosítója a tokenből jön.
- Felhasználónkénti rate limit és napi költségkeret be van állítva az alkalmazásban is, nem csak a szolgáltatói konzolon.
- A kontextusba csak a feladathoz szükséges adat kerül, bérlőnként szűrve (retrieval RLS-sel vagy kötelező metaadat szűrővel).
- A system promptban nincs titok, kulcs, belső URL, jogosultsági logika.
Kimenet
- A kimenet Zod sémán megy át, hiba esetén korlátozott javító kör, utána determinisztikus hiba.
- A modell által adott azonosítók jogosultsága a kódban ellenőrzött.
- HTML kimenet tisztítva, külső kép és link allowlist, CSP beállítva.
- Terminálba vagy naplóba írt kimenetből a vezérlőkarakterek kiszűrve.
Eszközök (ha vannak)
- Minden eszköz szintbe sorolva, a külső kommunikáció jóváhagyással.
- Lethal trifecta ellenőrizve.
- Lépés, token, idő és költség limit, kill switch.
- Idempotencia kulcs az író eszközökön, audit napló.
Minőség
- Eval készlet lefutott, a biztonsági esetek 100 százalékon, az összesített arány a küszöb felett.
- Legalább egy közvetett prompt injekciós eset (dokumentumba vagy emailbe rejtett utasítás) a tesztek között.
- A modell ID és a prompt verziója naplózva minden válasznál, hogy egy regresszió visszakereshető legyen.
Üzemeltetés és megfelelés
- Timeout és újrapróbálás exponenciális várakozással, a szolgáltató kiesésekor értelmes hibaüzenet.
- Naplóban PII maszkolva, megőrzési idő meghatározva.
- Szolgáltatói DPA, EU régió vagy adatrezidencia, tanításra való felhasználás kizárva, ha személyes adat érintett.
- Chatbotnál a felületen jelezve, hogy AI-val beszél a felhasználó (AI Act 50. cikk), generált tartalomnál a jelölés megoldva.
- Magas kockázatú felhasználásnál (HR, hitel, oktatás) a kockázati besorolás és a dokumentáció elindítva, jogi vélemény kérve.
Átvilágító kérdések egy meglévő, AI generált projekthez
Egy kész, vibecodinggal készült kódbázis átvilágításakor ebben a sorrendben haladunk.
- Lefut a tipikus hibáknál bemutatott átvilágító szkript, az eredmény prioritás szerint rendezve (kint lévő titok, RLS hiány, IDOR elöl).
- Lekérdezzük az RLS nélküli táblákat, a
using (true)policykat és a Supabase advisor jelzéseit. - Minden végpontnál megnézzük, honnan jön a felhasználó azonosítója, és hol van tulajdonos ellenőrzés.
- Az összes LLM hívásnál feltérképezzük, mi kerül a kontextusba, hova megy a kimenet, és van-e limit.
- A függőségek listáján megjelöljük a fölöslegeseket és a gyanúsakat.
- Ellenőrizzük, hogy a tesztek elbuknak-e elrontott kóddal.
- Az eredmény táblázatban kerül átadásra hiba, hatás, javítás és sürgősség szerint, a kritikus tételek (kiszivárgott titok, nyitott tábla) külön kiemelve, azonnali teendővel (kulcsrotáció, RLS bekapcsolás).
Források
A források 2026 októberében ellenőrizve.
| Forrás | Év | Mire használtuk |
|---|---|---|
| OWASP Top 10 for LLM Applications 2025 és 2026 (genai.owasp.org) | 2024 vége, 2026. augusztus | A tíz kockázat, a 2026-os átrendeződés |
| OWASP Top 10 for Agentic Applications 2026 | 2025. december | ASI01 és ASI10 közötti kockázatok |
| OWASP MCP Top 10 (owasp.org/www-project-mcp-top-10) | 2025, béta | MCP specifikus kockázatok |
| Model Context Protocol specifikáció, Authorization és Security Best Practices (2025-06-18, 2025-11-25, 2026-07-28) | 2025, 2026 | Confused deputy, token passthrough, SSRF, helyi szerver, scope, állapotmentesség |
| Simon Willison, The lethal trifecta for AI agents | 2025. június | A három képesség modellje |
| Simon Willison, The Dual LLM pattern | 2023 | Privilegizált és karanténba zárt modell |
| Debenedetti és mtsai, Defeating Prompt Injections by Design (CaMeL), arXiv 2503.18813 | 2025 | Képesség alapú, programozott védekezés |
| Beurer-Kellner és mtsai, Design Patterns for Securing LLM Agents against Prompt Injections, arXiv 2506.08837 | 2025 | A hat minta |
| Invariant Labs, MCP tool poisoning kutatások | 2025 | Tool poisoning, shadowing, GitHub MCP eset |
| Anthropic, Building Effective Agents | 2024. december | Workflow és agent minták |
| NIST AI 100-1 (AI RMF), NIST AI 600-1, NIST IR 8596 tervezet | 2023, 2024, 2025 | Kockázatkezelési keret |
| ISO/IEC 42001:2023 | 2023 | AI irányítási rendszer |
| EU AI Act (2024/1689) és Digital Omnibus on AI (2026/1744) | 2024, 2026 | Kötelezettségek és határidők |
| MITRE ATLAS | folyamatos | Támadási taktikák és esettanulmányok |
| Perry és mtsai, Do Users Write More Insecure Code with AI Assistants?, ACM CCS | 2023 | Biztonsági hatás és túlzott magabiztosság |
| Veracode, 2025 GenAI Code Security Report | 2025. július | A generált kód sérülékenységi aránya |
| Spracklen és mtsai, We Have a Package for You!, USENIX Security | 2025 | Csomag hallucináció, slopsquatting |
| METR, Measuring the Impact of Early 2025 AI on Experienced Open Source Developer Productivity | 2025. július | Érzett és mért produktivitás |
| CVE-2025-48757 (Lovable, Supabase RLS) | 2025 | Hiányzó RLS generált appokban |
| Andrej Karpathy, vibe coding (X, 2025. február 2.) és agentic engineering (2026. február) | 2025, 2026 | A fogalom és utódja |
Állapot 2026 októberében. A szöveg szakmai összefoglaló, nem jogi tanácsadás, a szabványok és jogszabályok aktuális szövegét a kiadótól érdemes ellenőrizni.