Generált Kód Biztonsága: A GitHub Copilot és ChatGPT kódjavaslatainak kritikus felülvizsgálata

2025.10.17.
AI Biztonság Blog

A Kód, amit nem te írtál: A Copilot és ChatGPT rejtett biztonsági aknái

Ülsz a gép előtt, épp egy komplex funkción dolgozol. Az agyad már zsong a sokadik kávétól, a határidő pedig ott liheg a nyakadban. Beírsz egy kommentet: // function to upload user profile picture, resize to 200x200, and save to S3. És bumm. A GitHub Copilot, mint egy digitális dzsinn, kitölti a képernyőt egy látszólag tökéletes kódrészlettel. Elfogadod. Mész tovább. Kész a feladat, a főnök elégedett, te pedig hős vagy.

Vagy mégsem?

Kapcsolati űrlap

AI Biztonság kérdésed van? Itt elérsz minket:

Feltetted magadnak a kérdést, hogy az a tíz sor kód, amit egyetlen Tab leütéssel beillesztettél a production rendszeredbe, honnan jött? Tényleg érted, mit csinál minden egyes sora? Vagy csak bízol a varázslatban?

Az AI-alapú kódasszisztensek, mint a Copilot vagy a ChatGPT, elképesztő produktivitási ugrást hoztak. Olyanok, mint egy végtelenül türelmes, mindentudó junior fejlesztő, aki sosem fárad el. De van egy bökkenő. Ez a junior fejlesztő az egész internetről tanult. A makulátlanul dokumentált, biztonságos vállalati kódbázisokból éppúgy, mint a tíz évvel ezelőtti, sebezhető tutorialokból a Stack Overflow-n, vagy a sebtében összedobott, hardkódolt API kulcsokkal teli GitHub repókból.

És ez, barátom, egy teljesen új dimenzióját nyitja meg a biztonsági rémálmoknak.

A nagy félreértés: Az AI nem „gondolkodik”, hanem mintázatot ismétel

Mielőtt belevágnánk a sűrűjébe, tegyünk rendbe egy alapvető tévhitet. A nagy nyelvi modellek (LLM-ek), amik ezeket az eszközöket hajtják, nem értik a kódot úgy, ahogy te. Nem fut le a fejükben egy logikai folyamat a biztonsági implikációkról. Ők valami egészen mást csinálnak.

Képzeld el az LLM-et úgy, mint egy hihetetlenül tehetséges, de a világról semmit sem tudó zenészt. Ha lejátszol neki ezermilliárd dalt a poptól a metálon át a klasszikus zenéig, egy idő után elképesztő pontossággal fogja tudni, hogy egy adott akkordmenet után melyik a legvalószínűbb következő akkord. Képes lesz „komponálni” egy dalt, ami megszólalásig hasonlít egy Mozart-szonátára vagy egy Rammstein-számra. De fogalma sem lesz arról, mit jelent a melankólia, a düh, vagy hogy miért vált ki egy adott hangsor feszültséget a hallgatóból.

Az LLM-ek pontosan ezt teszik, csak szavakkal és kóddal. Ők statisztikai mintázatfelismerő gépek. Amikor te beírsz egy promptot, az LLM azt kérdezi magától: „A tréning adathalmazomban látott billiárdnyi példa alapján, mi a legvalószínűbb tokensorozat (szó, karakter, kódelem), ami ezt a bemenetet követi?”

Az AI nem a legjobb megoldást adja. A statisztikailag legvalószínűbb megoldást adja. És a kettő nagyon, nagyon nem ugyanaz.

Ez a kulcs. Ha a tréning adatok tele vannak egy adott sebezhetőséggel (mert mondjuk az egy gyakori, de rossz programozási minta), akkor az AI boldogan fogja neked is azt javasolni, mert statisztikailag az a „helyes” válasz. Nem azért, mert gonosz, hanem azért, mert ezt tanulta.

Fejlesztői Prompt „SQL query to find user” LLM („Stochasztikus Papagáj”) „A tréning adatok alapján mi a legvalószínűbb kódrészlet?” Biztonságos Kód (Paraméterezett query) (Kisebb valószínűség) Sebezhető Kód (String összefűzés) (Nagyobb valószínűség)

A generált kód hét főbűne

Rendben, elég az elméletből. Nézzük a gyakorlatot. Mik azok a konkrét, húsbavágó sebezhetőségek, amiket ezek az eszközök nap mint nap a fejlesztők gépére varázsolnak? Íme a személyes „kedvenceim” listája, amikkel red teamerként a leggyakrabban találkozom.

1. A feledékeny titkok bűne (Hardcoded Credentials)

Ez az abszolút klasszikus, a lista első helyezettje. Megkérsz egy AI-t, hogy írjon egy kódrészletet, ami egy adatbázishoz, egy API-hoz, vagy egy felhős szolgáltatáshoz csatlakozik. Mi a legegyszerűbb módja ennek bemutatására? Természetesen placeholder (vagy néha ijesztően valósnak tűnő) adatokkal közvetlenül a kódban.

A tipikus forgatókönyv:

Te beírod: // Python script to connect to a PostgreSQL database

A Copilot generálja:


import psycopg2

conn = psycopg2.connect(
    host="localhost",
    database="mydatabase",
    user="admin",
    password="password123"
)

# ... rest of the code
    

És már kész is a baj. A fejlesztő látja, hogy működik, gyorsan átírja a saját adataira, és mivel siet, elfelejti kiszervezni környezeti változókba vagy egy secret managerbe. Pár hónappal később a kód bekerül egy publikus GitHub repóba, és a scriptek, amik hardkódolt kulcsokra vadásznak, percek alatt megtalálják.

Miért csinálja ezt az AI? Mert a tréning adatainak óriási része tutorialokból, dokumentációkból és „gyors és piszkos” megoldásokból áll, ahol ez a bevett gyakorlat a koncepció bemutatására. Az AI nem tudja, hogy ez egy éles rendszer része lesz. Csak a leggyakoribb mintát követi.

2. A vak bizalom bűne (SQL Injection)

Az SQL injection (SQLi) egy ősi, de még mindig elképesztően hatékony támadási forma. Lényege, hogy a támadó olyan adatot ad meg egy beviteli mezőben, amit a szerveroldali kód aztán közvetlenül belefűz egy adatbázis-lekérdezésbe, megváltoztatva annak eredeti jelentését.

A tipikus forgatókönyv:

Te beírod: // PHP function to get user info from database by username

A ChatGPT generálja:


function getUserInfo($username) {
    $db = new mysqli("localhost", "user", "pass", "db");
    $sql = "SELECT * FROM users WHERE username = '" . $username . "'";
    $result = $db->query($sql);
    // ... process result
}
    

Ez a kód egy nyitott kapu. Ha egy támadó ' OR '1'='1 értéket ad meg felhasználónévként, a lekérdezés így fog kinézni: SELECT * FROM users WHERE username = '' OR '1'='1'. Ez a feltétel mindig igaz, így a lekérdezés visszaadja az összes felhasználót a táblából. Innen már csak egy lépés a teljes adatbázis kompromittálása.

Miért csinálja ezt az AI? Mert a string-összefűzés a lekérdezések építésének legegyszerűbb, leginkább magától értetődő módja. A biztonságos, paraméterezett lekérdezések (prepared statements) használata egy extra lépés, ami a neten fellelhető rengeteg régi kódban és tutorialban egyszerűen nincs benne. Az AI a könnyebb, gyakoribb utat választja.

SQL Injection: A generált kód csapdája SEBEZHETŐ (String összefűzés): $sql = „SELECT * FROM users WHERE name = ‘” + userInput + „‘”; Ha a userInput = ‘ OR ‘1’=’1 A futtatott SQL: SELECT * FROM users WHERE name = ” OR ‘1’=’1′; -> MINDEN VISSZAAD! BIZTONSÁGOS (Paraméterezett lekérdezés): $sql = „SELECT * FROM users WHERE name = ?”;

3. A lusta importőr bűne (Elavult/Sebezhető Függőségek)

A modern szoftverfejlesztés a függőségekre épül. Ritkán írunk meg mindent nulláról, inkább behúzunk egy csomó külső csomagot. Az AI ebben is segít: javasol könyvtárakat, és megírja a hozzájuk tartozó import/require utasításokat. De honnan tudja, hogy az a könyvtár, amit javasol, biztonságos-e?

Sehonnan.

Az AI modellje egy adott időpontban készült pillanatkép a neten elérhető kódról. Ha a tréning adatok 2021-ből származnak, akkor a 2021-ben népszerű könyvtárakat és verziókat fogja javasolni. Simán előfordulhat, hogy azóta abban a verzióban találtak egy kritikus sebezhetőséget (CVE-t).

A tipikus forgatókönyv:

Te beírod: // Node.js code to parse XML from user input

A Copilot generálja:


const libxmljs = require("libxmljs"); // Javasol egy régi, népszerű könyvtárat

function parseXml(xmlString) {
    // A sebezhető `parseXml` függvény használata, ami pl. XXE támadásra adhat lehetőséget
    const xmlDoc = libxmljs.parseXml(xmlString); 
    return xmlDoc;
}
    

Lehet, hogy a libxmljs egy régebbi verziójában, amit a modell a tréning adatok alapján ismer, van egy ismert XML External Entity (XXE) sebezhetőség. Te, a fejlesztő, csak annyit látsz, hogy „jé, van egy ilyen XML-parser, szuper”, és már használod is. A háttérben pedig egy időzített bomba ketyeg.

4. A kriptográfiai tévelygés bűne (Gyenge Titkosítás)

A kriptográfia nehéz. Nagyon nehéz. Tele van aknákkal, és egy apró hiba is katasztrofális következményekkel járhat. Az AI pedig, mivel nem érti a mögöttes matematikát és a biztonsági elveket, hajlamos a legegyszerűbb, leggyakrabban látott – és gyakran leggyengébb – megoldásokat javasolni.

Gyakori hibák:

  • Elavult algoritmusok: Jelszavak hashelésére MD5-öt vagy SHA1-et javasol, amik már évtizedek óta töröttnek számítanak.
  • Hardkódolt kulcsok és sók (salt): A titkosító kulcsot vagy a hasheléshez használt sót közvetlenül a kódban tárolja.
  • Helytelen implementáció: Rosszul használja a titkosítási módokat (pl. ECB), vagy nem használ inicializációs vektort (IV), ami sebezhetővé teszi az egészet.
  • Gyenge véletlenszám-generátorok: Nem kriptográfiailag biztonságos véletlenszám-generátort használ kulcsok vagy tokenek létrehozásához.

Amikor azt kéred, hogy „hash a user password”, az AI a múlt lenyomatát adja vissza. És a múlt tele volt MD5-tel.

5. A kontextus nélküli kód bűne (Logikai Hibák és Race Conditions)

Ez egy sokkal alattomosabb probléma. Az AI egy kis ablakon keresztül látja a kódodat. Nem érti a teljes architektúrát, a párhuzamosan futó szálakat, vagy az üzleti logikát. Csak az adott függvényre vagy kódrészletre koncentrál.

Ennek eredményeként olyan kódot generálhat, ami önmagában szintaktikailag helyes, de a nagyobb rendszer kontextusában súlyos logikai hibát vagy sebezhetőséget okoz.

A tipikus forgatókönyv:

Képzelj el egy webshopot. Van egy függvény, ami ellenőrzi a raktárkészletet, és egy másik, ami végrehajtja a vásárlást. Megkéred az AI-t, hogy írjon egy kódot, ami „leellenőrzi, hogy van-e elég termék, és ha igen, csökkenti a készletet”.


// Generated by AI
function purchaseItem(itemId, quantity) {
    const stock = checkStock(itemId); // 1. Készlet ellenőrzése
    if (stock >= quantity) {
        // Valamilyen művelet itt, pl. fizetés feldolgozása
        updateStock(itemId, stock - quantity); // 2. Készlet csökkentése
        return true;
    }
    return false;
}
    

Mi itt a probléma? Ha két felhasználó pontosan ugyanabban a pillanatban próbálja megvenni az utolsó darab terméket, mindkét kérés átjuthat az if ellenőrzésen, mielőtt bármelyik frissítené a készletet. Ez egy klasszikus race condition. Az eredmény: negatív raktárkészlet és csalódott ügyfelek. Az AI nem gondolkodik tranzakciókban vagy lockolásban, mert ahhoz a teljes rendszer ismerete kellene.

6. A hallucináló könyvtáros bűne (Nem létező Függőségek és API-k)

Az LLM-ek néha „hallucinálnak”. Ez azt jelenti, hogy magabiztosan állítanak valamit, ami egyszerűen nem igaz. A kódgenerálás világában ez azt jelenti, hogy kitalálnak függvényneveket, API végpontokat, vagy akár komplett könyvtárakat, amik nem léteznek.

Ez elsőre csak egy bosszantó dolognak tűnik, de komoly biztonsági kockázata van. A fejlesztő látja a javasolt, nem létező super-cool-parser-v2 csomagot. Rákeres. Nem találja. De talál egy nagyon hasonló nevű, super-cool-parser-v2-fixed csomagot, amit valaki pont tegnap töltött fel a csomagkezelőbe. Letölti, és ezzel egy rosszindulatú kódot (malware-t) juttatott a rendszerébe. Ez a typosquatting támadások egy új, AI-által felturbózott formája.

Az AI által hallucinált, nem létező csomagnév egyenes út lehet egy támadó által előre odakészített, rosszindulatú csomaghoz.

7. A túlzott bőbeszédűség bűne (Felesleges Debug Információk)

Amikor hibakezelő kódot kérünk, az AI hajlamos nagyon részletes, „segítőkész” hibaüzeneteket generálni. Ezek gyakran tartalmaznak olyan érzékeny információkat, mint a belső stack trace-ek, adatbázis sémák, fájlrendszer-útvonalak vagy változók értékei.

Fejlesztés közben ez hasznos. Éles rendszerben viszont aranybánya egy támadónak. Ezek az információk (Improper Error Handling) segítenek feltérképezni a rendszer belső működését, és megtalálni a gyenge pontokat.

Az alábbi táblázat összefoglalja a leggyakoribb sebezhetőségeket és a mögöttük álló okokat.

Sebezhetőség Típusa Példa Miért generálja ezt az AI? Red Teamer Tipp
Hardcoded Secrets password="pass123" a kódban A tréning adatok (tutorialok) tele vannak ilyen példákkal. Ez a legegyszerűbb minta. Keress a kódban kulcsszavakra, mint ‘password’, ‘key’, ‘secret’, ‘token’, és vizsgáld a hozzájuk rendelt literálokat.
SQL Injection "SELECT ... WHERE id='" + userInput + "'" A string összefűzés statisztikailag gyakoribb a régi kódbázisokban, mint a biztonságosabb paraméterezés. Minden, felhasználói bemenetből származó adatot gyanúval kezelj, ami adatbázis-lekérdezésbe kerül.
Vulnerable Dependencies import library_with_known_cve A modell tudása egy adott időpontban „befagyott”, nem ismeri a legújabb sebezhetőségeket. Használj automata dependency scannereket (pl. Snyk, Dependabot) a CI/CD pipeline-ban.
Weak Cryptography hash = md5(password) Az MD5 és SHA1 rengeteg régi kódban szerepel, így az AI számára „valószínű” megoldásnak tűnik. Keress rá az elavult algoritmusok neveire (MD5, SHA1, DES, ECB mód). Auditáld a kulcskezelést.
Race Conditions Check-then-act logika szinkronizáció nélkül. Az AI nem látja a teljes, párhuzamosan futó rendszert, csak egy izolált kódrészletet. Gondold végig a kritikus erőforrásokhoz (fájlok, adatbázis-rekordok) való hozzáférést. Hol lehet ütközés?

A védekezés nem opció, hanem kötelesség: Hogyan szelídítsd meg a fenevadat?

Oké, a kép elég sötét. Most akkor dobjuk ki a Copilotot és a ChatGPT-t, és írjunk mindent újra kézzel, mint a régi szép időkben? Szó sincs róla. Ezek fantasztikus eszközök, ha a helyükön kezeljük őket. A kulcs a gondolkodásmód megváltoztatása.

Ne úgy tekints az AI-ra, mint egy mindentudó orákulumra. Tekints rá úgy, mint egy hihetetlenül gyors, de tapasztalatlan és naiv gyakornokra. Ötleteket ad, megírja a boilerplate kódot, de a végső felelősség a tiéd, a senior fejlesztőé.

A te új, AI-biztos fejlesztői folyamatod

1. A Nulla Bizalom Elve (Zero Trust Mindset): Soha, de soha ne fogadj el egyetlen sor AI által generált kódot sem anélkül, hogy végigolvasnád és megértenéd. Nincs kivétel. Ha nem érted, mit csinál, ne illeszd be! Kérdezz rá az AI-tól, hogy magyarázza el, vagy keress utána a dokumentációban.

2. A Kontextus Király (Prompt Engineering): Ne légy lusta a promptjaiddal! Minél több kontextust adsz az AI-nak, annál jobb és biztonságosabb kódot fog generálni. Ne csak annyit írj, hogy „írj egy fájlfeltöltő funkciót”. Írd ezt:

„Írj egy Node.js/Express fájlfeltöltő funkciót a ‘multer’ könyvtár használatával. A funkció csak ‘image/jpeg’ és ‘image/png’ típusú fájlokat fogadjon el, a méretkorlát 5 MB. A fájlnévből távolítson el minden speciális karaktert, és mentsd el a fájlt egy egyedi, UUID-alapú néven a ‘/uploads’ mappába.”

Ezzel már a prompt szintjén beépítettél több biztonsági ellenőrzést.

3. Gép a gép ellen (Automatizált Ellenőrzés): Az emberi figyelmetlenség ellen a legjobb védekezés az automatizálás.

  • SAST (Static Application Security Testing): Integrálj a CI/CD folyamatodba olyan eszközöket, mint a SonarQube, Snyk Code, vagy a GitHub CodeQL. Ezek még a commit előtt képesek kiszűrni a fent említett sebezhetőségek nagy részét. Ők a te éber őrszemeid.
  • Dependency Scanning: Használd a GitHub Dependabotját, az Snyk Open Source-t vagy az OWASP Dependency-Check-et. Ezek folyamatosan figyelik a projekted függőségeit, és riasztanak, ha egy ismert sebezhetőség felüti a fejét.

4. A támadó fejével gondolkodni (Manuális felülvizsgálat): A gépek nem találnak meg mindent. A kódreview során tedd fel magadnak a kérdést: „Hogyan tudnék visszaélni ezzel a kóddal?”. Mi történik, ha nullát, negatív számot, egy 2 GB-os fájlt, vagy egy SQL parancsot adok meg bemenetként? Játszd el a támadó szerepét!

Az alábbi diagram egy lehetséges biztonságos fejlesztési folyamatot vázol fel AI asszisztensek használatával.

Ötlet/Feladat 1. Prompt írása (Kontextussal!) AI Kódgenerálás (Copilot, ChatGPT) 2. Manuális Kód Felülvizsgálat „Megértem? Biztonságosnak tűnik?” 3. Automata Ellenőrzés (SAST, Dependency Scan) (Snyk, SonarQube, Dependabot) Minden rendben? Igen Commit Nem Javítás/Újragondolás

Záró gondolatok: A felelősség a tiéd

Az AI kódasszisztensek itt vannak, és itt is maradnak. Nem fognak eltűnni, sőt, egyre okosabbak és egyre mélyebben beépülnek a fejlesztői munkafolyamatokba. Tagadni a létezésüket vagy félni tőlük zsákutca. A feladatunk az, hogy megtanuljunk együtt élni velük, és megértsük a korlátaikat és a veszélyeiket.

A legnagyobb sebezhetőség nem a Copilot által generált kódban van. Hanem a fejlesztő fejében, aki vakon bízik benne.

Minden egyes Tab leütés, amivel elfogadsz egy javaslatot, egy biztonsági döntés. A te döntésed. A te felelősséged. A kérdés nem az, hogy az AI fog-e hibázni. A kérdés az, hogy te ott leszel-e, hogy észrevedd.