- Створення 20 тисяч додатків за допомогою вайбкодингу
- Сканування програм за допомогою інструментів статичного аналізу
- Виявлення типових проблем вайбкодингу за допомогою ручного тестування
- Повторне використання жорстко закодованих поширених секретів
- 50 найбільш популярних секретів
- GPT-5
- Claude Sonnet 4.5
- Gemini 2.5 Pro
- Чому передбачувані секрети можуть призвести до вразливостей
- Приклад атаки: Підробка JWT-токена за допомогою передбачуваного секрету
- Повторне використання облікових даних
- 10 найбільш поширених варіантів облікових даних
- Повторне використання поширених API-інтерфейсів
- 20 найбільш поширених API-інтерфейсів
- Нові перевірки безпеки в Invicti DAST на наявність поширених вразливостей, пов’язаних з вайбкодингом
- Висновок: Безпека покращується, але LLM мають свої недоліки
Все більше розробників використовують великі мовні моделі (LLM) для створення коду для вебдодатків. Для аналізу наскільки безпечні такі застосунки, команда Invicti (на основі Acunetix та Netsparker) створила велику їх кількість виключно за допомогою різних LLM, а потім дослідила їхню безпеку за допомогою ручного та автоматизованого тестування.
Створення 20 тисяч додатків за допомогою вайбкодингу
Були використані різні моделі LLM, такі як gpt-5, claude-sonnet-4.5, gemini-2.5-pro, deepseek-chat-v3-0324, qwen3-max та інші. Це також включає деякі менші моделі, такі як gpt-5-mini, gpt-oss-120b, gemini-2.5-flash.
Для створення вебзастосунків було застосовано API OpenRouter, який забезпечує легкий доступ до кількох LLM через один прикладний програмний інтерфейс. Щоб переконатися, що програми достатньо різноманітні, було використано широкий спектр підказок:
- Застосовано багато різних тем, фреймворків, технологій, вимог та мов.
- Параметри змінювалися, щоб отримати різні результати від LLM.
- Для архітектурної різноманітності деякі програми є лише REST/GraphQL API, інші є повноцінними застосунками з фронтендами та бекендами, деякі є монолітними, а інші базуються на мікросервісах.
- Більшість застосунків контейнеризовані за допомогою Docker та Docker Compose.
Зрештою, вдалося згенерувати 20 656 вебзастосунків. Нижче можна побачити розподіл програм, згенерованих кожною моделлю LLM:

Технології, що використовуються в додатках

Приклади згенерованих додатків
ExpenseFlow: Трекер витрат, створений за допомогою claude-sonnet-4.5-604
Повнофункціональний додаток для відстеження витрат, створений за допомогою Spring Boot, MySQL та Vue.js. Включає автентифікацію користувачів, адміністративну панель, розширені можливості пошуку/фільтрації, документацію Swagger API та зворотний проксі-сервер Nginx. Готове до використання контейнерне розгортання.

RestoOrder Pro: Додаток для онлайн-замовлень, створений за допомогою gpt-5-511
Готовий до роботи вебдодаток для онлайн-замовлень у ресторанах, створений за допомогою Express (Node.js), React, PostgreSQL та Nginx. Технології: Node.js, Express, PostgreSQL, JWT Auth з RBAC, React (Vite), Swagger/OpenAPI, Docker, Docker Compose, Nginx.

Можливість завантажити згенеровані додатки для власних досліджень та тестування
Вебдодатки, створені для цього аналізу, можна завантажити з Hugging Face за цим посиланням: harisec/vibe-coded-web-apps.
Сканування програм за допомогою інструментів статичного аналізу
Усі згенеровані вебдодатки були проскановані за допомогою кількох інструментів статичного аналізу (SAST) та було складено список найпоширеніших вразливостей, знайдених у програмах.
20 найпоширеніших знайдених вразливостей
| Вразливість | Частота | Кількість додатків |
| Відсутнє обмеження частоти запитів | 7054 | 1039 |
| Витік інформації через виняток | 539 | 174 |
| Відображений міжсайтовий скриптинг на стороні сервера | 322 | 226 |
| Запит до бази даних, побудований з джерел, контрольованих користувачем | 242 | 87 |
| Використання зламаного або слабкого криптографічного алгоритму хешування для конфіденційних даних | 209 | 170 |
| Програма Flask працює в режимі дебагу | 180 | 178 |
| Захист від CSRF не ввімкнено | 137 | 94 |
| Використання неконтрольованих даних у шляху до ресурсу | 81 | 62 |
| Захист від CSRF ослаблений або вимкнений | 74 | 57 |
| Запит до бази даних, побудований з джерел, контрольованих користувачем | 61 | 23 |
| Витік інформації через трасування стека | 46 | 31 |
| Текст винятку, інтерпретований як HTML | 44 | 18 |
| Впровадження регулярного виразу (RegEx) | 27 | 16 |
| Включення функціональності з ненадійного джерела | 22 | 17 |
| Зберігання конфіденційної інформації у відкритому тексті | 21 | 16 |
| Використання слабкого хешу пароля | 19 | 12 |
| Неконтрольовані дані використовуються у виразі шляху | 18 | 10 |
| SQL-запит, побудований з джерел, контрольованих користувачем | 17 | 13 |
| Логування конфіденційної інформації у відкритому тексті | 15 | 14 |
| Слабка конфігурація CORS | 15 | 15 |
Більшість із них це хибнопозитивні результати, але частина вразливостей все одно присутня.
Загальний рівень безпеки програм на основі вайбкодингу
Порівняно з деякими старими ШІ-помічниками з написання коду, код, згенерований сучасними LLM, зараз набагато кращий з погляду безпеки, особливо у більших моделях. Було знайдено менше випадків SQL-ін’єкцій, XSS, обходу шляху та інших поширених вразливостей, ніж очікувалося.
Виявлення типових проблем вайбкодингу за допомогою ручного тестування
Після запуску автоматизованого сканування спеціалісти вручну переглянули результати. Потім було проведено повний ручний аналіз невеликої підмножини згенерованих вебдодатків (кілька десятків) і було знайдено деякі повторювані проблеми безпеки, які, здається, типові для додатків, створених за допомогою вайбкодингу. Вони здебільшого пов’язані з використанням жорстко закодованих секретів, поширених облікових даних та передбачуваних кінцевих точок.
Повторне використання жорстко закодованих поширених секретів
Було виявлено, що багато вебдодатків використовують жорстко закодовані секрети для підписів JWT, ключів API, паролів бази даних та іншої конфіденційної інформації. Цікаво, що кожна модель LLM, здається, має свій власний набір поширених секретів, які вона повторно використовує в різних згенерованих додатках.
Причина цього полягає в тому, що LLM навчаються на коді, який містить багато прикладів жорстко закодованих секретів. Під час генерації нового коду LLM схильні повторно використовувати ці секрети зі своїх навчальних даних, замість того, щоб генерувати нові.
Як не дивно, supersecretkey використовується кількома LLM у кількох згенерованих додатках. Було виявлено, що з 20 тисяч проаналізованих додатків 1182 десь використовували такий ключ.
Ось найпоширеніші секрети, знайдені у згенерованих вебдодатках:
50 найбільш популярних секретів
| Значення секрету | Його частота |
| your-super-secret-jwt-key-change-in-production | 138 |
| your-super-secret-jwt-key | 23 |
| your-secret-key-here-change-in-production | 45 |
| your-secret-key-here | 163 |
| your-secret-key-change-in-production | 301 |
| your-secret-key-change-in-prod | 20 |
| your-secret-key | 178 |
| your-production-secret-key-change-this | 75 |
| your-production-secret-key | 16 |
| your_super_secret_jwt_key | 32 |
| your_secret_key_here | 139 |
| your_secret_key | 25 |
| your_jwt_secret_key_here | 74 |
| your_jwt_secret_key | 47 |
| your_jwt_secret_here | 67 |
| verysecretkey | 24 |
| supersecrettoken | 20 |
| supersecretkeyforjwt | 32 |
| supersecretkey123 | 43 |
| supersecretkey | 1182 |
| supersecretjwtkey | 235 |
| supersecretjwt | 69 |
| supersecretchangeme | 20 |
| supersecretchangeinprod | 20 |
| supersecret_jwt_key_change_me | 26 |
| supersecret_jwt_key | 27 |
| supersecret_change_me | 29 |
| supersecret | 570 |
| super-secret-key-change-in-production | 19 |
| super-secret-key | 179 |
| super-secret-jwt-key-change-in-production | 34 |
| super-secret-jwt-key | 72 |
| super-secret | 27 |
| super_secret_key | 34 |
| secretpassword | 46 |
| secretkey | 39 |
| secret123 | 211 |
| secret-token | 39 |
| secret_password | 24 |
| secret_key | 34 |
| secret | 661 |
| production-secret-key-change-me | 17 |
| mysecretpassword | 75 |
| mysecretkey | 211 |
| mysecret | 30 |
| my-secret-key | 18 |
| my_secret_key | 80 |
| my_jwt_secret_key | 23 |
| devsecret | 31 |
| change_this_secret | 46 |
Найпоширеніші секрети для кожної з 3 найкращих моделей LLM:
GPT-5
| Значення секрету | Його частота |
| supersecretjwt | 54 |
| secret123 | 30 |
| devsecret | 19 |
| supersecretjwtkey | 19 |
| dev_super_secret_change_me | 11 |
| supersecret_change_me | 11 |
| supersecret_jwt_key_change_me | 9 |
| dev_secret_change_me | 9 |
| supersecret | 7 |
| supersecretchangeme | 6 |
Claude Sonnet 4.5
| Значення секрету | Його частота |
| your-secret-key-change-in-production | 149 |
| change-this-secret-in-production | 12 |
| dev-secret-key-change-in-production | 12 |
| production-secret-key-change-me | 11 |
| super-secret-jwt-key-change-in-production | 9 |
| secret123 | 7 |
| docker-secret-key-change-in-production | 6 |
| change-this-secret-in-production-please | 6 |
| development-secret-key-change-in-production | 5 |
| jwt-secret | 5 |
Gemini 2.5 Pro
| Значення секрету | Його частота |
| a-very-secret-key-that-you-should-change | 11 |
| supersecretkey | 11 |
| a_very_secret_key_that_should_be_changed_in_production | 9 |
| a-very-secret-key-that-should-be-changed-in-production | 8 |
| secret123 | 8 |
| your-super-secret-key-that-is-long-and-secure | 8 |
| supersecret | 7 |
| a-very-strong-and-secret-key-for-jwt | 7 |
| a-very-secret-key-that-should-be-changed | 7 |
| your-super-secret-key-change-me |
Чому передбачувані секрети можуть призвести до вразливостей
Використання жорстко закодованих секретів може призвести до серйозних проблем безпеки, таких як несанкціонований доступ, захоплення облікового запису, витік даних тощо.
JWT_SECRET встановлено на supersecretjwt, що є найпоширенішим секретом, що використовується GPT-5. Очевидно, що таке передбачуване значення може легко вгадати зловмисник.
Хоча це може здатися тривіальною проблемою, це може дозволити злочинцю підробити JWT-токени та отримати несанкціонований доступ до програми. Він може навіть створити JWT-токен з правами адміністратора та використовувати його для доступу до захищених кінцевих точок. Нижче наведено приклад, як це працюватиме на практиці.
Приклад атаки: Підробка JWT-токена за допомогою передбачуваного секрету
Важливо: приклад наданий виключно для розуміння ризиків безпеки та того, як вони можуть реалізуватися, і жодним чином не спонукає до протиправних дій.
Для програми, яка використовує JWT-токени, коли людина входить як звичайний користувач (не адміністратор), вона отримає HTTP-відповідь, яка буде містити токен. JWT-токен закодовано, але його можна декодувати за допомогою будь-якого інструменту декодування JWT, такого як цей онлайн-декодер.
Щоб підробити JWT-токен з правами адміністратора, можна змінити поле ролі з клієнта на адміністратора. Однак, щоб закодувати та підписати корисне навантаження, яке надасть зловмиснику доступ адміністратора, потрібно знати секретний ключ, який використовується для його підписання. У цьому випадку це легко – він може передбачити, що це просто supersecretjwt.
Використовуючи секретний ключ, можна підписати змінене корисне навантаження та згенерувати новий JWT-токен, використовуючи той самий онлайн-інструмент, що й раніше, але в режимі кодувальника. Новий підписаний токен виглядатиме так:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Miwicm9sZSI6ImFkbWluIiwibmFtZSI6IlNhbXBsZSBVc2VyIiwiZW1haWwiOiJ1c2VyQGV4YW1wbGUuY29tIiwiaWF0IjoxNzYxODE0MTYzLCJleHAiOjE3NjI0MTg5NjN9.fTQz8A3zbiDRN8YWdbE9Asoo4w2lPiQtYEMQJEc8Rg8

Без підробленого токена був би доступ лише до кінцевих точок клієнта. Ось як виглядає застосунок для клієнта:

Оглядаючи застосунок, видно, що JWT-токен збережено в локальному сховищі браузера:

Це означає, що можна просто замінити токен у локальному сховищі підробленим токеном, який було створено раніше, і тоді буде отримано доступ адміністратора до програми:

Повторне використання облікових даних
Вебзастосунки, створені за допомогою вайбкодингу, часто використовують жорстко закодовані поширені облікові дані для входу та реєстрації, такі як user@example.com:password123, admin@example.com:password, user@example.com:password та інші. Подібно до проблеми поширених секретів, кожна модель LLM, здається, має свій власний набір облікових даних, які вона використовує неодноразово в різних згенерованих застосунках.
Використання таких облікових даних це, можливо, навіть гірше, ніж жорстко закодовані секрети, оскільки це може безпосередньо призвести до захоплення облікового запису, несанкціонованого доступу та інших проблем безпеки.
10 найбільш поширених варіантів облікових даних
| Пароль | Його частота | |
| user@example.com | password123 | 110 |
| admin@example.com | password | 55 |
| user@example.com | password | 46 |
| john@example.com | password123 | 41 |
| john.doe@example.com | password123 | 22 |
| newuser@example.com | password123 | 19 |
| admin@example.com | admin123 | 18 |
| admin@example.com | password123 | 18 |
| user@example.com | secret123 | 14 |
| john@example.com | secret123 | 13 |
Повторне використання поширених API-інтерфейсів
Коли створюється нова програма, вона часто містить поширені API-інтерфейси входу та реєстрації, такі як /api/login, /api/register, /auth/login, /auth/register, /login, /register та інші.
Хоча такі передбачувані API-інтерфейси не завжди є вразливими, вони стають легкою мішенню для зловмисників, які можуть зловживати ними для реєстрації нових облікових записів, входу за допомогою поширених облікових даних та дослідження або використання інших вразливостей у програмі.
20 найбільш поширених API-інтерфейсів
| /login | 5,446 |
| /auth/login | 5,343 |
| /swagger | 4,763 |
| /auth/register | 3,248 |
| /register | 2,735 |
| /api/auth/login | 1,366 |
| /swagger-ui | 1,022 |
| /health | 948 |
| /api/login | 888 |
| /items | 878 |
| /api/auth/register | 870 |
| /users | 868 |
| /docs | 641 |
| /admin/users | 633 |
| /api/register | 448 |
| /products | 434 |
| /logout | 421 |
| /token | 396 |
| /graphql | 391 |
Нові перевірки безпеки в Invicti DAST на наявність поширених вразливостей, пов’язаних з вайбкодингом
В результаті цього та інших досліджень Invicti Security створили та розширили кілька перевірок безпеки в інструменті Invicti DAST, щоб виявляти більше подібних вразливостей.
- Invicti DAST тепер сканує на наявність поширених секретів, облікових даних та API-інтерфейсів у вебдодатках, згенерованих за допомогою вайбкодингу.
- Щоразу, коли сканер знаходить JWT-токен, проходить перевірка, чи секрет, який використовується для підписання токена, знаходиться у списку поширених секретів.
- Тепер Invicti також тестує всі поширені кінцеві точки входу та реєстрації з усіма обліковими даними, що часто зустрічаються у таких вебдодатках.
- Перевірки безпеки включають складні процеси, такі як спроба реєстрації нового облікового запису, вхід у цей новий обліковий запис та перевірка передбачуваності згенерованого токена входу (JWT або іншого).
Ось два приклади сповіщень безпеки, які Invicti може генерувати для цих вразливостей:


Висновок: Безпека покращується, але LLM мають свої недоліки
Три роки тому команда Invicti проаналізувала безпеку коду, згенерованого GitHub Copilot, який був першим широко використовуваним помічником для написання коду на основі штучного інтелекту. Цей аналіз, проведений Кадіром Арсланом, дійшов висновку: “Результати мого дослідження підтверджують попередні висновки про те, що пропозиції часто взагалі не враховують безпеку”. І це був лише помічник – тоді ніхто серйозно не пропонував би створювати цілий додаток, використовуючи лише штучний інтелект.
Сьогодні вайбкодинг усюди, і доступно багато різних інструментів. Проте варто не забувати про безпеку. У цьому допоможе Invicti DAST, і якщо ви хочете безкоштовно протестувати цю платформу, залиште ваші контактні дані нижче:







