# Dziewięć błędów, które AI wpisuje w Twój kod

> Hardcoded secrets, SQL injection, path traversal, słaba kryptografia. Wzorce, które powtarzają się w kodzie z LLM, i sposób na każdy.

- URL: https://artcode.software/pl/blog/top-10-cwe-w-kodzie-generowanym-przez-ai
- Author: Artur Kluz, Founder, AI architect (https://www.linkedin.com/in/arturkluz/)
- Published: 2026-07-08
- Updated: 2026-10-16
- Language: pl
- Tags: bezpieczenstwo, cwe, generowanie-kodu, inzynieria
- Publisher: ArtCode Software (https://artcode.software)

Kod generowany przez LLM ma rozpoznawalny odcisk palca. Po audytach kodu wdrożonego między 2024 a 2026, który zawierał funkcje generowane przez AI w historii commitów, te same dziewięć słabości pojawia się mniej więcej w tej samej kolejności. Ten post wymienia je w przybliżonej częstości, wyjaśnia co sprawia, że kod generowany przez model jest podatny w każdym przypadku, i daje jeden konkretny wzorzec prewencji.

Lista to nie OWASP Top 10. To wyspecjalizowany podzbiór dla kodu, który regulowane MŚP wdraża na produkcję: web API, wewnętrzne serwisy, pipeline danych, integracje. Zachowanie modelu, bias danych treningowych i wzorce indukowane promptem wyjaśniają, dlaczego te konkretne CWE się powtarzają.

**W skrócie.** W kodzie generowanym przez modele językowe powtarza się dziewięć słabości, m.in. CWE-798 (zaszyte poświadczenia), CWE-89 (SQL injection przez konkatenację) i CWE-79 (XSS). Przyczyny to skład danych treningowych i skróty z promptów. Ograniczają je testy OWASP i CWE, linting w pre-commit oraz cienka, audytowana warstwa wrapperów.

## 1. CWE-798 - Hardcoded credentials w kodzie źródłowym

Najczęstszy z dużym marginesem. Modele trenowane na publicznym GitHubie widziały tysiące repozytoriów, gdzie klucze API, URI baz danych i sekrety JWT są commitowane raz i usuwane w panice. Odtwarzają wzorzec w generowanym kodzie z tą samą ludzką plausibility. Typowe symptomy: literały `API_KEY = "sk-..."`, bloki w stylu `.env` wbudowane w Python lub JavaScript, connection stringi dla Postgres i MongoDB z poświadczeniami inline.

**Prewencja:** traktuj każde poświadczenie jako wartość wstrzykiwaną w runtime. Konfiguracja ze zmiennych środowiskowych lub secret managera (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). Hook pre-commit ze skanerem sekretów (`gitleaks`, `trufflehog`) blokuje przypadkowe commity. Dodaj krok CI, który wysypuje build przy sekretach w diffie, nawet jeśli poprzedni PR nie miał tego problemu.

## 2. CWE-89 - SQL injection przez konkatenację stringów

Modele domyślnie tworzą query stringowe, gdy prompt to "funkcja filtrująca użytkowników po emailu." Wzorzec `f"SELECT * FROM users WHERE email = '{email}'"` pojawia się w generowanym kodzie z częstością sugerującą, że dane treningowe mają go w zdrowej podaży. Model jest też podatny na budowanie dynamicznych klauzul ORDER BY lub whitelist kolumn z wejścia użytkownika bez parametryzacji, nawet gdy WHERE clause jest poprawne.

**Prewencja:** używaj wyłącznie parametryzowanych zapytań. W Python to `cursor.execute("SELECT ... WHERE email = %s", (email,))` z `psycopg` lub równoważnym. W JavaScript prepared statements przez `pg`, `mysql2` lub ORM. Reguła lintera (`python-bandit`, `eslint-plugin-security`) łapie wzorce konkatenacji. Dodaj zestaw testów SQL injection, który CI uruchamia na każdym endpoincie, w tym tych, których nikt nie ruszał od roku.

## 3. CWE-79 - Cross-site scripting przez niezescapowany rendering

Dla React i Vue to często dyrektywy `dangerouslySetInnerHTML` i `v-html` stosowane do wejścia użytkownika lub do stringów generowanych przez model, które zawierają dane użytkownika. Dla server-renderowanych szablonów Jinja2 lub Django brak dyscypliny `|safe` i HTML w wyjściu modelu. Wzorzec jest trudniejszy do wykrycia w code review niż SQL injection, bo podatność żyje w ścieżce danych, nie w przepływie sterowania.

**Prewencja:** domyślnie bezpieczny rendering. Traktuj każdy string przechodzący granicę zaufania jako tekst, nie HTML. Sanityzuj na granicy permisywno-bezpieczną whitelistą (`DOMPurify` dla przeglądarki, `bleach` dla Pythona). Jeśli produkt faktycznie renderuje HTML z kontrolowanego źródła, izoluj tę ścieżkę za jawną allow-listą i audytuj ją przy kolejnym security review.

## 4. CWE-22 - Path traversal przez niesanityzowane ścieżki plików

Modele czytające lub zapisujące pliki pod nazwami podanymi przez użytkownika bez sprawdzania sekwencji `../` lub ścieżek bezwzględnych to powtarzający się wzorzec, szczególnie w pipeline uploadu dokumentów, procesorach obrazów i importerach CSV. Model często łapie oczywiste przypadki (`..` w środku stringa), ale przepuszcza sztuczki Unicode normalisation lub ścieżki celujące w symlinki.

**Prewencja:** rozwiąż ścieżkę podaną przez użytkownika z kanonizacją docelowego systemu operacyjnego, potem zweryfikuj, że rozwiązana ścieżka jest wewnątrz dozwolonego roota. W Python `os.path.realpath` plus sprawdzenie prefixu rozwiązanej ścieżki. W Go `filepath.Clean` i to samo sprawdzenie prefixu. Nigdy nie konkatenuj wejścia użytkownika w ścieżkę podawaną do `open()` bez przechodzenia przez resolver.

## 5. CWE-327 - Użycie złamanego lub ryzykownego algorytmu kryptograficznego

Modele często domyślnie sięgają po `md5` dla "szybkiego hasha" lub `DES`, `RC4` albo tryb ECB AES dla "funkcji szyfrującej." Oba to złe domyślne wybory, które model traktuje jako kanoniczne. Subtelniejszy wariant to użycie `crypto.createCipher` (Node) lub `Random` (Java) bez silnego seeda, albo `random` zamiast `secrets` w kontekście kryptograficznym Pythona.

**Prewencja:** ogranicz powierzchnię kryptograficzną w Twoich wrapperach biblioteki standardowej. Wymuś użycie zatwierdzonych prymitywów (AES-GCM, ChaCha20-Poly1305, SHA-256 lub SHA-3 do haszowania). Przypnij algorytm na granicy importu, żeby deweloper (lub model) nie mógł przypadkiem użyć słabego prymitywu. Dodaj regułę lintera flagującą MD5, SHA-1, DES, RC4 poza testami legacy.

## 6. CWE-94 - Code injection przez dynamic evaluation

`eval()`, `exec()`, konstruktory `Function()` i silniki szablonów, które re-kompilują wejście użytkownika. Modele piszące funkcje pomocnicze w notebookach regularnie zawierają `eval(input_data)`, bo prompt mówił "ewaluuj wyrażenie." Powierzchnia ryzyka jest mała, ale wysoko uderzeniowa: pojedynczy `eval` w handlerze requestu wystawionym na wejście użytkownika to remote code execution.

**Prewencja:** brak `eval` w kodzie produkcyjnym. Dla dynamicznych szablonów użyj silnika bez logiki (Handlebars, Liquid w trybie ścisłym) i dozwolonego zestawu helperów. Dodaj hook pre-commit, który grepem łapie `eval(`, `exec(`, `Function(\"` i wysypuje build.

## 7. CWE-502 - Deserializacja niezaufanych danych

`pickle.loads`, `yaml.load` (bez `Loader=SafeLoader`), Java `ObjectInputStream`, PHP `unserialize` na wejściu użytkownika. Modele trenowane na notebookach data science są ciężkimi emitterami `pickle.loads`; wzorzec jest powszechny w generowanych pipeline.

**Prewencja:** YAML przez `yaml.safe_load`. Pickle zastąpiony round-tripem JSON lub Parquet. Java używa udokumentowanej allow-listy klas z filtrowaniem `ObjectInputStream`. Serializacja PHP zastąpiona przez `json_encode`/`json_decode`. Dla komunikacji między serwisami użyj typowanego schemy (Protocol Buffers, FlatBuffers, Avro) zamiast natywnej serializacji.

## 8. CWE-918 - Server-side request forgery

Modele budujące "image proxy" lub "walidator webhooka" często implementują forward requestu bez ograniczania docelowego URL. Request do `https://your-service/image?url=https://attacker.internal` staje się punktem oparcia dla endpointu metadanych chmury.

**Prewencja:** allow-list hostnamów, nie sztuczki parsowania URL. Rozwiąż hostname, sprawdź IP przeciwko prywatnym zakresom (`10.0.0.0/8`, `169.254.0.0/16` itd.) i odmów, jeśli rozwiązany adres nie jest na allow-liście. Uruchom proxy jako osobną tożsamość sieciową bez dostępu do wewnętrznych serwisów.

## 9. CWE-287 - Niepoprawna autentykacja

Najszersze CWE w tej liście, pojawiające się w wielu formach w kodzie generowanym przez AI: brak weryfikacji tokenu na chronionych endpointach, walidacja JWT bez sprawdzania podpisu, ciasteczka sesji ustawione bez `Secure` i `HttpOnly`, flow OAuth pomijające parametr state. Typowy wariant to model piszący `if user.get("role") == "admin":` bezpośrednio na danych requestu, z rolą pobraną z payloadu JWT, ale nigdy niezweryfikowaną.

**Prewencja:** scentralizuj autentykację. Jeden middleware, jedna biblioteka, jedno miejsce do audytu. Modele nie generują kodu autentykacji - wywołują funkcję w Twojej warstwie auth. Funkcja jest testowana, recenzowana i jest na śladzie audytowym. Zdecentralizowany auth to pierwotna przyczyna większości CWE-287 na tej liście.

## Dlaczego to się powtarza w kodzie generowanym przez AI

Trzy czynniki się nakładają. **Kompozycja danych treningowych.** Korpus nadreprezentuje kod tutorialowy, który z definicji jest permisywny (działa na laptopie dewelopera, nie w produkcyjnym threat modelu). Reprezentuje też kod produkcyjny z historycznymi podatnościami. Model uczy się wzorca powierzchni, nie threat modelu. **Skróty indukowane promptem.** Gdy prompt to "napisz endpoint Flask zwracający profil użytkownika", model przeskakuje od razu do happy path. Autentykacja, rate limiting i logowanie błędów są nieobecne, chyba że prompt je wymieni. Deweloper, który traktuje wyjście jako draft startowy, złapie to; ten, który traktuje jako gotowy kod, nie złapie. **Brak kontekstu.** Model nie wie, które pola są PII w Twojej domenie, które endpointy są admin-only, które integracje są osiągalne z publicznego internetu. Zadawanie właściwych pytań to zadanie inżynierskie; model nie może ich za ciebie zadać.

## Wzorce prewencji, które przecinają wszystkie dziewięć

Trzy kontrolki inżynierskie redukują powierzchnię ataku dla każdego CWE z tej listy. Harness testowy dla OWASP Top 10 i CWE Top 25 z fixtures z `OWASP Benchmark` i `NIST SARD`. Stos linting i pre-commit (Bandit, ESLint z `eslint-plugin-security`, Gosec, Semgrep), który łapie oczywiste wzorce. Granica architektoniczna, gdzie generowany kod woła do cienkiej, audytowanej warstwy wrapperów dla poświadczeń, systemu plików, sieci i dostępu do bazy danych.

## Jak to się łączy ze zgodnością z AI Act

Art. 15 AI Actu (dokładność, odporność, cyberbezpieczeństwo) uderza najmocniej właśnie w tę listę. Jeśli twój asystent AI generuje kod w regulowanym pipeline, output jest częścią systemu AI. Właściwości bezpieczeństwa outputu są właściwościami bezpieczeństwa systemu. Udokumentowany program prewencji dla powyższych CWE jest częścią oceny zgodności z art. 43.

ArtCode Software wdraża ten harness prewencyjny obok generatorów kodu AI w regulowanych polskich SaaS. Harness żyje w repo, działa w CI i jest referencją w model card. Jeśli potrzebujesz przeglądu tego, gdzie kod generowany przez AI jest obecnie w Twoim pipeline i który z tych dziewięciu wzorców jest najbardziej eksponowany, [Audyt AI Readiness](/pl#zalacznik-1) obejmuje przegląd próbek kodu pod kątem tej listy. Jeśli chcesz bieżącej ochrony w miarę ewolucji modelu i codebase, architekt AI może osadzić wzorce prewencji w Twoim procesie deweloperskim. Zakres opisuje [oferta](/pl#oferta).
