---
title: "Vibe coding: bezpečnostní rizika a 5 děr, které jsem ověřil"
description: "Co se kazí v aplikacích z vibe codingu: čísla ze tří studií a pět děr v přístupu, které jsem reprodukoval na lokálním Supabase, plus jak zkontrolovat tu svou."
url: "https://madsalt.tech/cs/blog/vibe-coding-security-risks/"
author: "Denys Zaichenko"
language: "cs"
published: 2026-10-24
---

# Vibe coding: bezpečnostní rizika a 5 děr, které jsem ověřil

TL;DR

Kód, který AI napíše, obvykle běží. Selhává to, kdo se dostane k datům. V auditu 200 nasazených aplikací z vibe codingu z roku 2026 mělo 91 % alespoň jednu zranitelnost a největší skupinou bylo porušené řízení přístupu. Pět děr v přístupu jsem reprodukoval na lokálním Supabase: jen s veřejným klíčem vydala tabulka bez RLS, politika vždy pravdivá, view i uniklý secret key všechny 3 ze 3 řádků. Zkontrolujte svou aplikaci nejdřív na tohle.

Jsem Denys, full-stack a AI inženýr. Opravuji aplikace postavené v Lovable, Bolt, Cursoru nebo Claude Code a většina z nich běží na Supabase. Tento článek shrnuje, co o bezpečnosti vibe codingu říká publikovaný výzkum a co jsem viděl, když jsem běžné chyby záměrně znovu postavil.

## Jaká jsou bezpečnostní rizika vibe codingu?

Hlavním rizikem je porušené řízení přístupu: data, která může číst nebo měnit kterýkoli návštěvník, protože pravidlo, které ho mělo zastavit, chybí, je příliš volné nebo je obejité. Následuje injekce a slabá autentizace. Tři nezávislé studie ukazují stejným směrem:

| Studie                                                                                                                                  | Co se testovalo                                                                   | Co se zjistilo                                                                                                                                                                                  |
| --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Deng, Fan a Meng, arXiv 2606.23130](https://arxiv.org/abs/2606.23130), červen 2026                                                     | 200 nasazených aplikací postavených s Claude Code a Lovable, audit ručně i agenty | 182 z 200 aplikací (91 %) mělo alespoň jednu zranitelnost; 65,77 % z 1 186 nálezů bylo Critical nebo High; porušené řízení přístupu bylo největší kategorií, ve 64 % aplikací                   |
| [Escape](https://escape.tech/blog/methodology-how-we-discovered-vulnerabilities-apps-built-with-vibe-coding/), říjen 2025               | 5 600 veřejných aplikací z Lovable, Base44, Create.xyz a dalších, pasivní sken    | Více než 2 000 zranitelností s vysokým dopadem, více než 400 odhalených tajemství, 175 případů odhalených osobních údajů; hlavní příčinou byla špatně nastavená oprávnění, zejména Supabase RLS |
| [Veracode GenAI Code Security Report](https://www.veracode.com/resources/analyst-reports/2026-genai-code-security-report/), 2025 a 2026 | 80 programovacích úloh zadaných více než 100 modelům                              | Jen 55 % úloh dalo v roce 2025 bezpečný kód; průměrná úspěšnost v roce 2026 byla 56 %, napříč velikostmi modelů i roky stejná                                                                   |

Studie měří různé věci, takže procenta nejdou sečíst do jednoho čísla. Společný mají tvar: kód funguje a mezery jsou na hranici důvěry.

## Které díry jsem reprodukoval?

Na lokálním Supabase (CLI 2.109.1, Postgres 17.6, PostgREST 14.14) jsem založil jednu tabulku `orders` se třemi řádky fiktivních zákazníků. Pak jsem volal Data API tak, jak to dělá prohlížeč, s veřejným klíčem (publishable key), který nese každý frontend na Supabase, a měnil vždy jednu věc.

![Co dostal jeden veřejný klíč z jedné tabulky. Lokální Supabase, 3 řádky fiktivních objednávek, vždy jeden požadavek. Tabulka bez RLS: Publishable key → orders, RLS vypnuté → 3 z 3 řádků; RLS zapnuté, zatím bez politiky: Publishable key → orders, RLS zapnuté → 0 řádků; Politika using (true): Publishable key → using (true) → 3 z 3 řádků; View bez security_invoker: Publishable key → view order_summary → 3 z 3 řádků; Secret key v kódu prohlížeče: Secret key → BYPASSRLS → 3 z 3 řádků.](https://madsalt.tech/charts/cs/vibe-coding-security-risks.svg)

*Obrázek 1. Moje reprodukce na lokálním Supabase (Postgres 17.6, PostgREST 14.14), 23. října 2026.*

| Nastavení                       | Co dostal veřejný klíč                          | Proč                                                                                      |
| ------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Tabulka bez RLS                 | Všechny 3 řádky a vložení vrátilo `201 Created` | Výchozí granty dovolují `anon` číst i zapisovat a nic řádky nefiltruje                    |
| RLS zapnuté, bez politiky       | `[]`, prázdný seznam                            | RLS bez politiky zamítne vše pro `anon` i `authenticated`                                 |
| Politika `using (true)`         | Všechny 3 řádky                                 | Politika existuje, takže tabulka vypadá chráněně, ale povoluje každý řádek                |
| View nad chráněnou tabulkou     | Všechny 3 řádky                                 | View běží s právy svého vlastníka, pokud nemá `security_invoker = true`; s ním vrátí `[]` |
| Secret key ve frontendovém kódu | Všechny 3 řádky                                 | Secret key se mapuje na `service_role`, která má `BYPASSRLS`                              |

Druhý řádek je nebezpečný moment. RLS je zapnuté a aplikace ukazuje prázdný seznam, takže vypadá rozbitě. Nejrychlejší prompt, který to „opraví“, je politika, která povolí všechno, tedy třetí řádek. Tato smyčka, chyba a pak oprava, která rozšíří přístup, je vzorec, který v aplikacích z vibe codingu potkávám nejčastěji, a proto „RLS je zapnuté“ samo o sobě říká málo.

## Proč kód psaný AI selhává v řízení přístupu?

Agent je odměňován za kód, který běží. Prázdný seznam nebo `401` vypadá jako chyba a oprava, která ho odstraní, je často ta, která přístup otevře. Studie z arXivu vede svých 1 186 nálezů k osmi opakujícím se způsobům selhání, seskupeným jako vady paměti, cíle a znalostí agentů, a zjistila, že lepší prompting počet děr snížil, ale neodstranil.

Druhým důvodem je architektura. Aplikace z Lovable nebo Bolt obvykle nemá vlastní backend: prohlížeč mluví s databází přímo přes Data API. Každé pravidlo, které chrání data zákazníků, musí žít v Postgresu jako granty, politiky a funkce, a nic z toho není vidět v náhledu aplikace, kde jste přihlášeni jako vlastník. Supabase tu mění jednu výchozí hodnotu: od [30. října 2026](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically) se nové tabulky ve stávajících projektech už automaticky nezpřístupňují Data API. Na mém stacku odpověděla tabulka bez grantu `42501 permission denied` s nápovědou, která jmenuje chybějící `GRANT`. To zastaví první řádek tabulky výše pro nové tabulky, ale ne zbylé čtyři, ani tabulky, které už existují.

## Co dalšího se kazí mimo databázi?

Stejné studie uvádějí rizika, která s RLS nemají nic společného:

- **Tajemství v bundlu.** Escape našel více než 400 odhalených tajemství, včetně klíčů OpenAI a administrátorských klíčů plateb. Cokoli doručené do prohlížeče je veřejné.
- **Ochrany tras jen v Reactu.** Stránka, která přesměruje odhlášené uživatele, má za sebou pořád API, které odpoví komukoli.
- **Limity požadavků, které se nikdy nespustí.** Na hostovaném projektu Supabase, který jsem zkoumal, se počítadlo uložené v paměti edge funkce s každým požadavkem vynulovalo. Popsal jsem to ve svém [checklistu zabezpečení Lovable aplikace](https://madsalt.tech/cs/blog/lovable-app-security-checklist/).
- **Staré knihovny.** Escape napočítal 254 zranitelných instancí JavaScriptových knihoven ve veřejných assetech, často zděděných ze šablon.

## Jak zkontrolovat aplikaci z vibe codingu?

1. Otevřete aplikaci, DevTools → Network a najděte požadavky na `/rest/v1/`. Zkopírujte jeden jako cURL, odstraňte hlavičku `Authorization`, nechte `apikey` a spusťte ho. Pokud se vrátí data, vrátí se komukoli.
2. Prohledejte sestavený JavaScript na `sb_secret_` a `service_role`. Shoda je klíč, který je třeba vyměnit ještě dnes.
3. Spusťte bezplatnou [Kontrolu zabezpečení Supabase](https://madsalt.tech/cs/tools/supabase-security-check/). Čte katalog projektu a mezi svými 46 pravidly hlásí „RLS vypnuté u zpřístupněných tabulek“, „Politiky, které povolují každý řádek“, „Pohledy, které obcházejí RLS“ a „Výchozí oprávnění, která otevírají nové objekty API“: první čtyři řádky tabulky výše.
4. Testujte se dvěma uživateli ve dvou firmách, což je jediný test, který za vás skener neudělá. Jak ho dělám, je v [checklistu pro Lovable](https://madsalt.tech/cs/blog/lovable-app-security-checklist/) a [jak testovat Supabase RLS](https://madsalt.tech/cs/blog/how-to-test-supabase-rls/) ukazuje metodu na produkční aplikaci s obrazovkou oprávnění.

```bash
curl 'https://<project>.supabase.co/rest/v1/orders?select=*' \
  -H 'apikey: <the publishable key from your page>'
```

## Co tento test neukazuje

Moje reprodukce je jedna tabulka na lokálním stacku, postavená tak, aby ukázala každý mechanismus, ne sken skutečných aplikací. Čísla o rozšířenosti pocházejí ze tří studií, každá s vlastním vzorkem a metodou, odkazy výše. A čistý výsledek těchto pěti kontrol z aplikace bezpečnou neudělá: chyby v logice, například stráž, která pustí chybějící hodnotu, potřebují vlastní testy. Jedna taková je v poznámce o [NULL, které přeskočilo kontrolu oprávnění](https://madsalt.tech/cs/notes/plpgsql-if-not-null-fails-open/).

Postavili jste aplikaci s AI nástrojem?

Rád porovnám zkušenosti, co kontrolovat jako první. Bez nabídky.

[Ozvěte se](https://madsalt.tech/cs/#contact)
