Zpět na blog
    vibecoding
    zakladni-bezpecnost

    5 bezpečnostních chyb, které dělá každý vibecoder

    Nejčastější bezpečnostní chyby při vývoji s AI a jak se jim vyhnout

    TunaGuard tým18. května 20268 min

    Vibecoding je super, ale...

    Vibecoding změnil hru. Popíšeš co chceš, AI ti to napíše a ty to nasadíš. Žádné roky studia, žádné bootcampy, prostě vibes. A upřímně — je to úžasné. Demokratizace vývoje softwaru je skvělá věc.

    Ale je tu háček: AI ti napíše funkční kód, ne bezpečný kód. A to je zásadní rozdíl.

    ChatGPT, Claude nebo Copilot se snaží, aby tvůj kód fungoval. Ale bezpečnost? To pro ně není priorita, pokud se na ni explicitně nezeptáš. A i když se zeptáš, občas ti dají radu, která je... řekněme optimistická.

    Pojďme se podívat na 5 nejčastějších chyb, které vidíme u vibecoder projektů. Každou z nich jsme viděli mnohokrát a každá může mít reálné následky.

    1. Commitování secrets do Gitu

    Co se stane špatně

    Představ si tohle: vyvíjíš aplikaci, potřebuješ se připojit k databázi nebo volat API. AI ti vygeneruje kód a ty tam prostě vložíš svůj klíč:

    const stripe = require("stripe")("sk_live_AbCdEfGhIjKlMnOpQrStUvWx");
    

    Commitneš, pushneš na GitHub. Funguje to! Pak si uvědomíš chybu, klíč odstraníš a commitneš znovu. Problém vyřešen, ne?

    Ne. Git si pamatuje všechno. Každý commit, každá změna. Tvůj klíč je pořád v historii a kdokoliv ho tam najde.

    Real-world příklad

    V roce 2023 výzkumníci z GitGuardian našli na GitHubu přes 10 milionů nových tajných klíčů za jediný rok. Boti skenují každý veřejný commit v reálném čase. Když pushneš AWS klíč, za minuty ho někdo najde a začne na tvůj účet mineovat kryptoměny. Lidi dostávali faktury za desítky tisíc dolarů.

    A pozor — i privátní repo může uniknout. Stačí jeden screenshot, jeden fork, jeden neopatrný kolega.

    Jak to opravit

    1. Nikdy nedávej secrets do kódu. Používej environment proměnné:
    # .env (přidej do .gitignore!)
    STRIPE_KEY=sk_live_AbCdEfGhIjKlMnOpQrStUvWx
    
    const stripe = require("stripe")(process.env.STRIPE_KEY);
    
    1. Přidej pre-commit hook, který ti nedovolí commitnout secret:
    npx husky init
    npm install --save-dev @secretlint/secretlint-rule-preset-recommend secretlint
    
    1. Pokud jsi už secret commitnul, okamžitě ho revokuj (vygeneruj nový klíč). Mazání z historie nestačí — předpokládej, že ho někdo viděl.

    2. Default databázová hesla

    Co se stane špatně

    AI ti řekne: "Nastav si PostgreSQL databázi." Ty zadáš docker-compose up s konfigurací, kterou ti AI vygenerovalo:

    services:
      db:
        image: postgres:16
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
    

    Funguje to, tak proč to měnit, že? Protože každý útočník na světě zkouší nejdřív tyhle výchozí kombinace:

    • postgres / postgres
    • root / root
    • admin / admin
    • sa / password

    Real-world příklad

    Výzkum z roku 2024 ukázal, že tisíce databází na internetu jsou přístupné s defaultními hesly. Útočníci je najdou přes Shodan (vyhledávač pro zařízení připojená k internetu), připojí se a stáhnou všechna data. Někdy je zašifrují a požadují výkupné. Jen v MongoDB ransomware kampani z roku 2023 bylo zasaženo přes 22 000 databází.

    Jak to opravit

    1. Vždy nastav silné, unikátní heslo. Vygeneruj si ho:
    openssl rand -base64 32
    # Výstup: něco jako "K8x2mP9qR4wN7jT1vB6yH3cF0gA5eD8="
    
    1. Ulož heslo do .env souboru, ne do docker-compose.yml:
    services:
      db:
        image: postgres:16
        environment:
          POSTGRES_USER: ${DB_USER}
          POSTGRES_PASSWORD: ${DB_PASSWORD}
    
    1. Databáze nemá být přístupná z internetu. Pokud nemusí — a většinou nemusí — ať poslouchá jen na localhost nebo interní síti.

    3. Žádný rate limiting

    Co se stane špatně

    Máš registrační formulář nebo API endpoint. Funguje. Skvěle. Jenže nemáš žádný rate limiting — tedy omezení počtu requestů, které může jeden uživatel (nebo bot) poslat za určitý čas.

    Co se stane? Bot ti za minutu pošle 10 000 registrací. Nebo 50 000 pokusů o přihlášení. Nebo ti vyčerpá platbový API limit a ty dostaneš účet za stovky dolarů.

    Real-world příklad

    V roce 2024 několik malých SaaS startupů reportovalo, že jim boti přes nezabezpečené API volali OpenAI endpointy a nagenerovali jim účty za tisíce dolarů za jediný víkend. Žádný rate limiting, žádná autorizace — prostě otevřené API, které někdo našel.

    Jiný případ: e-shop bez rate limitingu na přihlašovacím formuláři. Útočník prostě zkoušel hesla ze seznamu (credential stuffing) a za hodinu měl přístup k desítkám účtů.

    Jak to opravit

    V Node.js/Express je to překvapivě jednoduché:

    const rateLimit = require("express-rate-limit");
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minut
      max: 100, // max 100 requestů za okno
      message: "Příliš mnoho požadavků, zkus to později",
    });
    
    app.use("/api/", limiter);
    

    Pro citlivé endpointy (přihlášení, registrace) použij přísnější limit:

    const loginLimiter = rateLimit({
      windowMs: 15 * 60 * 1000,
      max: 5, // jen 5 pokusů o přihlášení za 15 minut
      message: "Příliš mnoho pokusů o přihlášení",
    });
    
    app.use("/api/login", loginLimiter);
    

    Bonus tip: Pokud používáš Cloudflare (a měl bys), můžeš rate limiting nastavit přímo tam — ani se to nedostane k tvému serveru.

    4. Neaktualizované závislosti

    Co se stane špatně

    Spustíš npm audit a vidíš:

    found 47 vulnerabilities (12 moderate, 28 high, 7 critical)
    

    A co uděláš? Nic. Protože "ono to funguje" a aktualizace by mohla něco rozbít. Tak to tam necháš. Měsíce. Roky.

    Problém je, že ty "critical vulnerabilities" jsou známé bezpečnostní díry, ke kterým existují veřejně dostupné návody jak je zneužít. Útočník si přečte CVE popis, zjistí že tvoje appka používá zranitelnou verzi knihovny, a za pár minut je uvnitř.

    Real-world příklad

    Vzpomeň na Log4j (Log4Shell) z konce roku 2021. Jedna zranitelnost v jedné knihovně zasáhla miliony aplikací po celém světě. Stačilo poslat speciálně formátovaný string do logu a útočník mohl spustit libovolný kód na serveru. Firmy, které rychle aktualizovaly, byly v pohodě. Ty co ne? Některé řešily následky ještě o rok později.

    Jak to opravit

    1. Pravidelně kontroluj závislosti:
    npm audit
    
    1. Automatizuj aktualizace — nastav si Dependabot nebo Renovate na svém GitHubu. Budou ti automaticky vytvářet pull requesty s aktualizacemi.

    2. Neinstaluj zbytečné balíčky. Každá závislost je potenciální bezpečnostní riziko. AI ti rádo přidá knihovnu na každý problém — ale opravdu potřebuješ left-pad? Čím méně závislostí, tím menší útočná plocha.

    3. Zamykej verze v package-lock.json (nebo yarn.lock) a commituj tento soubor. Zabrání to situaci, kdy se ti na produkci nainstaluje jiná verze než na lokálu.

    5. Chybějící HTTPS

    Co se stane špatně

    Rozhodneš se, že HTTPS nepotřebuješ. "Je to jen malá appka, nic důležitého tam není." Jenže:

    • Kdokoliv na stejné síti může číst veškerou komunikaci mezi uživatelem a tvou appkou
    • Může modifikovat data cestou (man-in-the-middle útok)
    • Může krást session cookies a přihlásit se jako tvoji uživatelé

    A to platí i pro "malé appky." Pokud má tvoje aplikace přihlášení, má HTTPS smysl. Pokud přenáší jakákoliv osobní data, má HTTPS smysl. Pokud existuje na internetu, má HTTPS smysl.

    Real-world příklad

    Na bezpečnostních konferencích je klasická ukázka: výzkumník si sedne v kavárně, zapne Wireshark (nástroj na odposlech síťového provozu) a během pár minut vidí přihlašovací údaje lidí, kteří se připojují k HTTP stránkám. V roce 2024 Google Chrome začal aktivně varovat před HTTP stránkami — uživatelé jim prostě nevěří.

    Jak to opravit

    HTTPS je dnes zdarma. Žádné výmluvy.

    • Vercel, Netlify, Railway — HTTPS je automatické
    • VPS — použij Let's Encrypt:
    sudo certbot --nginx -d tvojedomena.cz
    
    • Cloudflare — zapni "Always Use HTTPS" jedním kliknutím

    Navíc přidej do své aplikace HSTS header, který prohlížečům říká, aby vždycky používaly HTTPS:

    app.use((req, res, next) => {
      res.setHeader(
        "Strict-Transport-Security",
        "max-age=31536000; includeSubDomains"
      );
      next();
    });
    

    Bonus: Jak o bezpečnost požádat AI

    Když používáš AI k generování kódu, přidej do promptu bezpečnostní požadavky:

    "Napiš mi registrační endpoint v Express.js. Použij bcrypt pro hashování hesel, přidej rate limiting, validuj vstupy, a ujisti se, že nelogujeme citlivá data."

    Čím konkrétnější jsi, tím lepší (a bezpečnější) kód dostaneš. AI není nepřítel bezpečnosti — jen mu musíš říct, co chceš.

    Shrnutí

    | Chyba | Řešení | |---|---| | Secrets v Gitu | Environment proměnné + .gitignore + pre-commit hook | | Default hesla | Silná, unikátní hesla generovaná náhodně | | Bez rate limitingu | express-rate-limit nebo Cloudflare | | Staré závislosti | Pravidelný npm audit + Dependabot | | Bez HTTPS | Let's Encrypt nebo managed platforma |

    Nechceš na nic zapomenout?

    Bezpečnost má spoustu detailů a je snadné něco přehlédnout. Proto jsme vytvořili TunaGuard — interaktivní bezpečnostní checklisty, které tě provedou vším krok za krokem.

    Projdi si naše bezpečnostní checklisty a ujisti se, že tvoje appka je v bezpečí. Protože jedna přehlédnutá chyba může znamenat velký problém.

    T

    TunaGuard tým

    Píšeme o bezpečnosti srozumitelně — pro vývojáře, vibecodery i všechny, kdo chtějí chránit svá data a aplikace.