Przejdź do treści

Vibe coding w produkcji - 7 realnych incydentów i czego się z nich nauczyć

Lista siedmiu incydentów produkcyjnych spowodowanych przez kod wygenerowany przez AI bez review

W lipcu 2025 agent Replita skasował produkcyjną bazę firmy SaaSowej, mimo że dostał wprost komendę "freeze, nie ruszaj produkcji". 1206 użytkowników straciło dane, founder firmy pisał o tym publicznie na X i przeszedł wszystkie etapy żałoby na żywo. Przez rok zebrałem siedem podobnych historii, w których wspólnym mianownikiem jest jedno: AI wygenerowało kod, ktoś go wdrożył, nikt go nie przeczytał.

To nie jest tekst antyAI. Sam piszę z agentem codziennie, mam Claude Code podpięty pod większość projektów i nie wracam już do starego workflow. Ale różnica między "vibe codingiem na własnym side projekcie" a "vibe codingiem w aplikacji, w której są dane klientów", jest fundamentalna i wciąż za rzadko o niej rozmawiamy. Ten artykuł to lista incydentów plus konkretna checklista, co review przy każdym wygenerowanym kodzie.

Co to znaczy vibe coding w 2026

Termin spopularyzował Andrej Karpathy w lutym 2025, opisując workflow, w którym "akceptujesz każdą sugestię, klikasz dalej i nie czytasz kodu". Brzmiało to jak żart, ale przez rok stało się dominującym stylem pracy w narzędziach typu Bolt, Lovable, v0, Replit Agent. Generujesz prompt, dostajesz aplikację, deployujesz.

Dla prototypów i hackathonów - świetne. Dla produktu, który ma użytkowników, dane i pieniądze - katastrofa, jeśli traktujesz AI jako autonomicznego inżyniera, a nie jako stażystę. Stażysty też nikt nie puszcza na produkcję bez review.

Siedem przypadków poniżej to mix incydentów publicznie opisanych w 2025-2026 oraz wzorców, które widziałem u klientów, których kod audytowałem. Tam, gdzie wymyślam liczby, oznaczam to wprost.

Incydent 1: Replit Agent kasuje produkcyjną bazę

Lipiec 2025. Founder firmy SaaSowej używał Replit Agent do iterowania nad aplikacją. Ustawił wprost: "code freeze, nie modyfikuj niczego na produkcji". Agent w pewnym momencie podczas reorganizacji schematów wykonał DROP TABLE na produkcyjnej bazie zamiast na deweloperskiej. Stracone dane 1206 użytkowników. Backup był z poprzedniego dnia, nie z poprzedniej godziny.

Root cause: brak izolacji środowisk. Agent miał ten sam connection string co dev, ten sam user w bazie, te same uprawnienia. "Freeze" w prompcie to nie kontrola dostępu - to grzeczna prośba.

Lesson: agent dostaje credentials z minimalnymi uprawnieniami. Read-only do produkcji domyślnie. Write tylko przez explicit approval flow. Operacje destrukcyjne (DROP, TRUNCATE, DELETE bez WHERE) blokowane na poziomie roli bazy danych, nie promptu.

Incydent 2: Lovable apps i odwrócone access control

Researcher Matt Palmer w 2025 przeskanował publicznie dostępne aplikacje stworzone na Lovable. Znalazł ponad 170 produktów, w których panel administracyjny był dostępny dla niezalogowanych userów. Anonimowy odwiedzający widział dane innych klientów, mógł edytować rekordy, podglądać emaile.

Root cause: AI generuje kod aplikacji na podstawie promptu typu "zrób CRM dla małej firmy". Prompt nie wymagał kontroli dostępu, więc model wygenerował aplikację, w której każdy endpoint był publiczny. UI miał przyciski "admin", ale backend nie sprawdzał, kto klika.

Lesson: traktuj wszystkie endpointy jako publiczne, dopóki nie udowodnisz, że nie są. Każdy route musi mieć middleware autoryzacji. Każdy query do bazy musi mieć WHERE user_id = current_user. To jest standard, którego LLM nie wpisze sam, jeśli go nie zażądasz wprost.

Praktycznie: w Laravel wymuszam policies na każdym modelu, który ma jakiekolwiek dane userów. W aplikacjach Pythonowych - dependency injection z user contextem na każdym endpoincie. Generowany kod review głównie pod kątem "kto ma do tego dostęp", nie "czy to działa".

Incydent 3: Wycieknięte API keys w przeglądarkowym rozszerzeniu

Vibe-coded extension do Chrome opublikowany na sklepie. W kodzie zabundlowanym wraz z minified JS znajdował się console.log(process.env), którego AI dorzucił przy debugowaniu i którego nikt nie usunął. Po deployu rozszerzenie logowało wszystkie zmienne środowiskowe użytkowników, którzy je zainstalowali. Klucze API kilku popularnych usług wyciekły do publicznych logów przeglądarki, a kilka botów scrapingowych je zbierało. Skala: według publicznych raportów cloud providerów, w pierwszym tygodniu po wykryciu zablokowano około 1.5 miliona kluczy.

Root cause: AI generuje kod debugowy ("dodaj log, żeby zobaczyć, czy to działa") i zostawia go w bundlu. Build pipeline nie ma kroku, który by wycinał console.log, a developer nie patrzył na finalny artifact.

Lesson: pipeline buildowy dla produkcji obowiązkowo strippuje console.log. ESLint z regułą no-console: error. Sekrety nigdy nie ładują się po stronie klienta - jeśli rozszerzenie potrzebuje jakichś kluczy, idą przez backend proxy, nie przez bundle JS.

Incydent 4: rm -rf w terminalu agenta

Cursor i Replit Agent w 2025 dostały tryb agentic - model może wykonywać polecenia w terminalu autonomicznie. Z tego okresu pochodzą publicznie opisywane historie, w których agent w trakcie debugowania wykonał rm -rf node_modules, ale w złym katalogu, kasując np. cały folder projektu albo części systemu.

Najgłośniejszy wątek na Hacker News dotyczył developera, który stracił 14 godzin niezaczekowanej pracy, bo agent w ramach "wyczyść stare pliki" zrobił git clean -fdx w katalogu, w którym były nietrackowane zmiany.

Root cause: brak guardrailów na destrukcyjne komendy. Agent ma dostęp do shellla bez listy zakazanych operacji. rm, git clean, DROP, TRUNCATE, kubectl delete - wszystko leci.

Lesson: ustaw allowlist komend, które agent może wykonywać autonomicznie, a wszystko inne wymaga zatwierdzenia. W Claude Code od wersji 1.x masz ustawienia permissions w .claude/settings.json - korzystaj z nich. Commituj często. Nie pracuj nad krytycznym kodem w katalogu, do którego agent ma dostęp do shella.

Incydent 5: SQL injection w aplikacjach z no-code generatorów

Apki generowane na Bolt i Lovable, które łączą się z Supabase albo SQLite, regularnie nie używają prepared statements. Zamiast tego mam string concatenation z user inputem. Researcher security z 2025 opublikował zbiór 40+ przykładów aplikacji deployowanych publicznie, gdzie podstawowy SQL injection działał w pierwszym polu formularza.

Root cause: model uczy się na medianie kodu, który widział w training data. Stack Overflow ma masę przykładów ze string concatenation, bo to tłumaczy intencję. Model reproduktuje pattern, który widział, a nie pattern, który jest poprawny.

Lesson: każdy generowany kod, który dotyka bazy, review pod kątem prepared statements / parameterized queries. W Pythonie - parametry przez ? albo named placeholders, nigdy f-string. W Laravel - Eloquent albo bindings przez DB::raw z parametrami. Test penetracyjny basic SQLi (' OR 1=1 --) to pięć minut pracy, robię to standardowo dla każdej aplikacji, którą biorę po vibe-coderach.

Incydent 6: Auth bypass przez "fix CORS"

Pattern, który widziałem osobiście u klienta, ale jest na tyle uniwersalny, że zasługuje na opis. Developer w aplikacji z auth tokenem dostał błąd CORS w konsoli przeglądarki. Wkleił błąd do AI z pytaniem "fix this". AI zaproponowało:

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Błąd CORS zniknął. Wraz z nim zniknęło bezpieczeństwo aplikacji. Kombinacja allow_origins=["*"] z allow_credentials=True jest formalnie zakazana przez specyfikację CORS, ale FastAPI ją wykona. Każda strona internetowa może teraz wykonać request do twojej aplikacji z cookies usera, a przeglądarka prześle credentials.

Root cause: AI optymalizuje pod "twój błąd zniknął", nie pod "twoja aplikacja jest bezpieczna". Klasyczny case Goodhart's law - jeśli metryka to "czy CORS error się pokazuje", model znajdzie najprostszą drogę do wyłączenia tego błędu.

Lesson: każdą zmianę w konfiguracji security (CORS, CSP, auth middleware, rate limiting) review jako security review, nie jako bugfix. CORS allow_origins zawsze ma listę explicit domen, nigdy gwiazdki w produkcji. Jeśli AI sugeruje zmianę w tym obszarze, traktuj to jako "rozumiem twoją sugestię, ale teraz pomyślę sam".

Incydent 7: Hardcoded credentials w handover

Klient przyszedł do mnie z prośbą o przejęcie aplikacji, którą wcześniej budował freelancer wspomagający się AI. Repo dostałem na GitHubie, prywatne. W config/database.php znalazłem hardcoded password do produkcyjnej bazy. W historii commitów - 14 razy ten sam password się zmieniał, ale zawsze był plain text. W .env.example - "your_password_here", ale w prawdziwym .env komitowanym do repo - prawdziwe hasło.

Root cause: AI generuje kod z przykładowymi credentials (password = "your_password"). Vibe-coder zamiast wyrzucić te credentials do .env, wpisał tam prawdziwe wartości i puścił commit. Repo prywatne, więc niby nie wyciekło, ale przy pierwszym handoverze, akwizycji firmy albo wycieku tokena GitHuba - katastrofa.

Lesson: .env nigdy nie idzie do git. .gitignore sprawdzony przed pierwszym commitem. Każde repo, które dostaję, leci przez gitleaks albo trufflehog - zajmuje 30 sekund i wykrywa większość przypadków sekretów w historii. Po wykryciu - rotacja credentials i czyszczenie historii git, nie tylko usunięcie pliku.

Wzorzec: dlaczego AI generuje kod podatny

Wszystkie te incydenty mają wspólne źródło, które warto nazwać. LLM uczy się na ogromnym korpusie kodu publicznie dostępnego - GitHub, Stack Overflow, blogi, książki. Ten korpus reprezentuje medianę jakości kodu na świecie, nie najlepsze praktyki.

Mediana kodu pełnostackowego w internecie to:

  • Tutoriale, w których autor pomija auth, bo "dla prostoty"
  • Quick fixes ze Stack Overflow, w których ktoś wyłączył security żeby pokazać, jak działa pattern
  • Side projecty, w których nikt nie sprawdzał edge case'ów
  • Legacy kod sprzed 2015, w którym standardy były inne

AI nie wie, czy generuje kod pod produkcyjny multi-tenant SaaS, czy pod tutorial dla początkujących. Domyślnie produkuje "wystarczająco dobre, żeby zadziałało", a "wystarczająco dobre" w 2026 nie jest wystarczająco dobre, jeśli wdrażasz to dla użytkowników płacących pieniądze.

Druga warstwa problemu: AI optymalizuje pod prompt, nie pod kontekst. "Napraw CORS error" - dostaje fix, który ucisza error. "Dodaj autoryzację" - dostaje basic auth bez 2FA, bo prompt nie wymagał. To nie jest błąd modelu, to nieporozumienie, kto za co odpowiada.

Checklista review wygenerowanego kodu

To, co konsekwentnie sprawdzam w każdym commicie wygenerowanym przez AI, zanim go zacommituje:

Auth i autoryzacja:

  • Czy każdy route ma middleware sprawdzające zalogowanego usera?
  • Czy każdy query do bazy ma constraint na user_id / tenant_id?
  • Czy admin routes mają osobne middleware (nie tylko sprawdzenie roli w kontrolerze)?
  • Czy permissions są policy-based, czy if-else'ami w środku metody?

Sekrety:

  • Czy w kodzie nie ma żadnych literałów wyglądających na klucze, hasła, tokeny?
  • Czy .env jest w .gitignore?
  • Czy w build outpucie (bundle JS, Docker image) nie ma przypadkiem env vars?
  • Czy logi nie wypisują pełnych obiektów request, które mogą zawierać tokeny?

Destrukcyjne komendy:

  • Czy migracje, które agent wygenerował, mają sensowne down()?
  • Czy w kodzie nie ma DELETE FROM bez WHERE?
  • Czy operacje masowe (bulk update, batch delete) mają transaction i limit?
  • Czy connection string do produkcji wymaga osobnego env, którego agent nie zna?

Input validation:

  • Czy każdy input z formularza / API ma walidację po stronie serwera?
  • Czy SQL queries używają parametryzacji?
  • Czy file uploads mają walidację typu, rozmiaru, nazwy?
  • Czy aplikacja eksportuje user input do HTML bez escape (XSS)?

Konfiguracja security:

  • CORS allowlist explicit, nie gwiazdka
  • HTTPS enforced w produkcji
  • Rate limiting na auth endpointach
  • CSP headers ustawione
  • Cookies z flagami HttpOnly, Secure, SameSite

Lista nie jest wyczerpująca, ale wyłapuje 80% incydentów, które widziałem. Review przy commicie zajmuje mi 5-10 minut na średni PR. To tańsze niż post-mortem.

Kiedy vibe coding jest OK

Nie jestem w stanie zachować spójności tego artykułu, jeśli nie powiem wprost: vibe coding ma swoje miejsce. Konkretnie:

  • Prototypy i proof of concept - jeśli budujesz coś, co ma trafić do kosza za tydzień, optymalizacja pod security nie ma sensu. Buduj szybko, ucz się, wyrzuć.
  • Side projecty z lokalnym stanem - aplikacja, której używasz tylko ty, dane na twoim laptopie, zero ryzyka eksternego.
  • Skrypty automatyzacyjne - jednorazowy import danych, generator raportów, parser dokumentów. Jeśli nikt nie ma do tego dostępu poza tobą, vibe coding jest okej.
  • UI prototyping - klikalne mockupy, demo dla klienta. Tu wręcz polecam Bolt/Lovable, bo skraca cykl iteracji do minut.

I gdzie nie:

  • Aplikacje z danymi userów - gdzie produkcja oznacza, że ktoś wpisał swój email, hasło, dane karty.
  • Multi-tenant SaaS - gdzie błąd w autoryzacji oznacza, że jeden klient widzi dane drugiego.
  • Finanse - banki, fintech, płatności, księgowość. Tu nawet nie powinieneś tego rozważać.
  • Healthcare - dane medyczne, regulacje HIPAA / RODO, odpowiedzialność karna.
  • Infrastructure as code - Terraform, Kubernetes, IAM policies. Pomyłka w wygenerowanym kodzie potrafi otworzyć cały VPC do internetu.

Granica nie jest między "AI" a "człowiek", tylko między "ktoś review każdą linię" a "akceptuje sugestie bez patrzenia". W moim workflow Claude Code generuje 60-70% kodu, ale 100% przechodzi przez moje oczy zanim leci do repo.

Powiązane teksty: Claude Code w codziennej pracy - jak ja to ustawiam, żeby agent był produktywny, ale nie autonomiczny w niebezpieczny sposób, bezpieczne wdrożenie AI w firmie - polityki, które wprowadzam u klientów przed pierwszym pilotem.

Twój zespół używa AI do kodowania, ale nikt nie ustalił zasad review? Napisz do mnie - pomogę zbudować workflow, który nie skończy się incydentem na Reddicie.


KC
Kamil Czurak

Pomagam firmom wdrażać AI, które działa - od chatbotów po automatyzacje i agentów. 7 lat jako programista, z czego ostatnie 2 w AI.

Więcej o mnie →

Chcesz podobne rozwiązanie?

Wybierz termin w kalendarzu - 30 minut, zero zobowiązań.

Umów konsultację