Чи безпечний ваш застосунок на Cursor?
Чи безпечно робити продакшн-застосунки в Cursor? Код зазвичай працює добре. «Працює» і «захищений» є різними перевірками, і сама собою йде лише одна.

Логотипи належать їхнім власникам і показані, щоб позначити сумісність.
Коротко
- Застосунок, зроблений у Cursor, зазвичай безпечно запускати. Чи безпечно його відкривати назовні, перевіряється окремо, і за вас цього ніхто не робить.
- Згенерований код відповідає на поставлене вами питання. Які рядки може бачити відвідувач, вирішує база даних.
- Звичний шлях, яким секретний ключ стає публічним: рефакторинг із сервера у браузер, а потім NEXT_PUBLIC_ чи VITE_, щоб помилка зникла.
Cursor дає вам справжній контроль (ваш репозиторій, ваші файли, ваш деплой), і це змінює те, де сидить ризик. Ви не гадаєте, що зробив білдер від вашого імені. Ви швидко переглядаєте багато працездатного коду й вирішуєте, що читати уважно.
Ось що гайд за гайдом подає неправильно: саме питання, чи пише ШІ небезпечний код, хибне. Згенерований код пишеться так, щоб задовольнити те, про що ви попросили. «Завантаж замовлення користувача» задовольняється кодом, що завантажує замовлення. У цій фразі не сказано чиї, тож у відповіді немає нічого, що це вирішує, а місце, якому належить це рішення, зовсім не той файл, який ви переглядаєте.
«Працює» і «захищений» – це дві різні перевірки
Сама собою йде лише одна.
Уявіть крамницю. Ваш застосунок є вітриною: кожна побудована вами сторінка вручається кожному відвідувачу цілком, бо браузер не намалює того, чого йому не надіслали. Ваша база даних є складом: окремою будівлею в інтернеті з власним замком і власною адресою.
Коли ви запускаєте застосунок і він працює, ви перевірили вітрину: для вас потрібні речі з'являються на потрібних екранах. Замок ви не перевіряли. До складу можна дістатися напряму, взагалі не проходячи крізь вашу крамницю, і те, що застосунок коректно вантажиться, нічого не каже про те, що він поверне тому, хто оминає парадні двері.
Це та перевірка, яка сама собою не йде в жодному проєкті, ані згенерованому, ані написаному вручну. Пропустити її стає легше, коли код надходить швидше, ніж ви встигаєте його читати.
Сам Cursor це інше питання, ніж застосунок, який ви з ним випустили, і саме його насправді ставить більшість: чи безпечний Cursor AI розглядає, що зберігає редактор, що робить не так код, який він пише, і чому ні те, ні те не дістає до того, що може відкрити незнайомець.
Де в проєкті на Cursor ключі йдуть не так
Майже завжди під час переїзду з сервера у браузер.
Є два різновиди облікових даних, і вони майже однакові на вигляд. Публічний
ключ називає ваш проєкт і більше нічого (sb_publishable_… у нових проєктах
Supabase, anon у старіших), і його зроблено, щоб жити у браузері. Секретний
ключ, sb_secret_… або старіший service_role, ігнорує кожне написане вами
правило й може читати та змінювати кожен рядок, який у вас є.
Послідовність, що публікує такий ключ, цілком буденна. Код, який використовував
секретний ключ на сервері, переносять у компонент, що виконується у браузері.
Значення повертається як undefined, тож змінну перейменовують під той префікс,
якого хоче інструмент складання (NEXT_PUBLIC_ у Next.js, VITE_ у Vite), і
застосунок починає працювати. Власна документація Vite прямо каже, що робить цей
префікс: ці значення пакуються у ваш вихідний код під час складання.
.gitignore тут не рятує. Він керує тим, що потрапляє в репозиторій, а
результат складання створюється потім. Якщо хочете напевно знати, який із ваших ключів який,
є перевірка на одну хвилину.
Перевірка, що належить базі даних
Row Level Security, якщо ваші дані в Supabase, є перемикачем для кожної таблиці, який рядок за рядком вирішує, кому що читати.
Це і є відповідь на проблему «завантаж замовлення». Замість довіряти кожному запиту в коді, що він фільтрує правильно, база даних відмовляється повертати рядки, на які відвідувач не має права, хоч би що казав запит і хоч би хто його написав. Одне правило, застосоване в єдиному місці, крізь яке має пройти кожен запит.
Дві дрібниці вирішують, чи є вона у вас. Supabase вмикає Row Level Security за замовчуванням для таблиць, створених у Table Editor панелі, і не вмикає для створених виконанням SQL, а саме так їх створює файл міграції. І налаштування лише вмикає перевірку; хто пройде, вирішує політика за ним, а політика може все одно дозволяти всім.
Як перевірити власний проєкт на Cursor приблизно за десять хвилин
Шукайте у власному результаті складання, а не у вихідному коді. Зберіть
застосунок, а потім пошукайте у згенерованих файлах service_role, sb_secret_
і sk_live_. Усе, що знайдеться, є опублікованим. Це швидше й чесніше за читання
вихідного коду, бо це саме те, що отримують відвідувачі.
Прочитайте свій файл середовища на предмет префіксів. Кожна змінна
NEXT_PUBLIC_ чи VITE_ є публічною за задумом. Про кожну спитайте себе, чи
надрукували б ви її на головній сторінці.
Відкрийте в Supabase Authentication → Policies. Будь-яку таблицю, у якої Row Level Security показано як вимкнену, може прочитати кожен, у кого є адреса вашого проєкту, а вона у вашому застосунку.
А потім подивіться ззовні. Наше безкоштовне сканування робить цей останній крок за вас: воно читає ваш живий сайт як відвідувач і дає оцінку приблизно за 20 секунд, без акаунта: сканувати застосунок.
Що робити
- Застосунок, який працює, склав одну перевірку. Чи відмовить база даних сторонньому, перевіряється окремо, і за вас цього ніхто не робить.
- Згенерований код відповідає на поставлене вами питання. Питання «які рядки може бачити ця людина» належить базі даних.
- Звичним шляхом, яким секретний ключ стає публічним, є рефакторинг із сервера у браузер, а за ним перейменування з префіксом.
.gitignoreзахищає ваш репозиторій, а не результат складання.- У Supabase таблиці, створені виконанням SQL, стартують без Row Level Security, і після ввімкнення кожен рядок лишається читабельним, доки політика не скаже інакше.
Зберіть проєкт і пошукайте в результаті service_role та sk_live_ перш за все
інше: це хвилина, і відповідь однозначна. Далі
10-хвилинний чекліст безпеки буде найкоротшим шляхом крізь решту.
Що насправді може піти не так із застосунком, зробленим у Cursor
Жоден із цих пунктів не означає, що ви зробили щось не так: це звичайні побічні ефекти того, що AI швидко пише код. Ось що варто перевірити:
Секретний ключ, вписаний прямо в код
Коли AI під'єднує сервіс, він іноді вписує ключ прямо в код, щоб усе запрацювало, і якщо цей код виконується у браузері, будь-хто може його прочитати. Деякі ключі й мають бути публічними, і це нормально; Reeve читає завантажений код застосунку, знаходить будь-які ключі й підказує, які безпечні, а які треба перенести на сервер.
Закомічений .env або відкрита папка .git
Ключі мають жити у файлі .env, який ніколи не потрапляє в реліз. Але легко випадково закомітити .env, або задеплоїти приховану папку .git, так, що вся історія, разом із ключами, стає доступною для завантаження. Reeve перевіряє, чи можна дістатися до будь-чого з цього ззовні.
Відкрита база даних (RLS вимкнено)
Якщо ваш застосунок зберігає дані (часто в Supabase або іншому Postgres), зазвичай є правило (Row Level Security), хто може читати чи змінювати кожен рядок. Якщо воно вимкнене, ваші таблиці можуть бути відкриті будь-кому, хто знайде адресу. Це найпоширеніша серйозна проблема, і вона невидима, доки не перевіриш.
Публічне сховище файлів
Якщо ваш застосунок приймає завантаження, вони живуть у «бакетах» сховища. Публічний бакет означає, що будь-хто може переглянути список або завантажити те, що всередині, тож приватний файл може стати видимим усім. Reeve перевіряє, чи можна переглянути список ваших бакетів; він ніколи не завантажує чужих файлів.
Увімкнені Source maps
«Карта коду» (source map) розкриває оригінальний код вашого застосунку будь-кому, хто подивиться. Корисно під час розробки, але в продакшні дає стороннім читабельну копію того, як влаштований застосунок, і полегшує пошук інших прогалин. Варто прибрати. Reeve перевіряє, чи не відкриті ваші карти.
Відсутні заголовки безпеки та відкриті ендпоінти
Невеликі налаштування, що підказують браузерам, як захищати ваших відвідувачів, а також те, чи відповідають точки доступу до даних будь-кому чи будь-якому сайту. Окремо це дрібниці; разом вони накопичуються. Reeve позначає те, чого бракує.
Що таке Reeve і чим він не є
Reeve є безкоштовною перевіркою ззовні в режимі читання, наче інспектор, який перевіряє двері, не заходячи всередину. Це швидко, і це ловить поширені помилки з великими наслідками. Це не повний аудит безпеки, і чиста оцінка не є гарантією: вона означає, що очевидні двері зачинені.
Cursor є редактором, а не хостингом, тож він не деплоїть і не охороняє ваш застосунок за вас; більше цього лежить на вас і на тому коді, що створив AI. Власні інструменти Cursor можуть допомогти переглядати код на ходу, а якщо ви використовуєте Supabase, її радник позначає проблеми з базою даних. Що додає Reeve: погляд ззовні на застосунок, який ви справді відправили в реліз, простими словами, за якими можна діяти. А якщо ви не хочете про це думати, ми можемо стежити за ним замість вас.
Хочете, щоб цим займалися, а не лише перевірили?
Reeve Care продовжує стежити за вашим застосунком, робить резервні копії даних і допомагає полагодити, коли щось ламається, щоб ви могли будувати далі, а не хвилюватися.
Дізнатися про Reeve CareПоширені запитання
Чи безпечний код, написаний AI в Cursor?
Це може бути хороший код, але «написаний AI» не означає «перевірений на безпеку». AI оптимізує під те, щоб усе працювало, а це іноді означає ключ не в тому місці або відсутнє правило бази даних. Дізнатися можна, лише перевіривши, що відкрито; Reeve робить це безкоштовно приблизно за 20 секунд.
Здається, я закомітив файл .env. Це небезпечно?
Може бути, якщо файл (чи прихована папка .git) досяжний на вашому задеплоєному сайті, бо він може містити живі ключі. Reeve перевіряє ззовні, чи можна їх завантажити, щоб ви знали, чи треба міняти ці ключі.
Як дізнатися, чи витікають API-ключі мого застосунку на Cursor?
Звичною причиною є ключ, вписаний прямо в код, що виконується у браузері. Reeve читає завантажений код застосунку, знаходить будь-які ключі й підказує, які безпечно робити публічними, а які треба перенести на сервер, не зберігаючи справжніх значень.
Чи змінить сканування щось у моєму застосунку?
Ні. Reeve дивиться лише на те, що вже публічне ззовні. Він ніколи не входить в акаунти, нічого не змінює й не завантажує ваших файлів. Режим читання, наче перевірка, чи замкнені двері, не заходячи всередину.
Чи пише Cursor небезпечний код?
Це хибне питання до будь-якого помічника, зокрема й до людини. Згенерований код пишеться так, щоб задовольнити те, про що ви попросили, і «нехай ця сторінка завантажує замовлення» задовольняється кодом, що завантажує всі замовлення. У запиті не було сказано, які саме, тож і у відповіді немає нічого, що це вирішує. Хоч би як ви сформулювали запит, правило про те, хто які рядки може читати, має жити в базі даних.
Мій файл .env у .gitignore. Я захищений?
Для вашого репозиторію здебільшого так. Але .gitignore жодним чином не впливає на те, що публікує ваш інструмент складання. Змінна з браузерним префіксом (NEXT_PUBLIC_ у Next.js, VITE_ у Vite) вкомпільовується у JavaScript, який завантажують ваші відвідувачі, хоч би де вона зберігалася; і вона лишається в історії версій, якщо файл колись комітили до появи правила.
Як перевірити, що застосунок насправді віддає назовні, замість читати код?
Відкрийте власний сайт, запустіть DevTools браузера й подивіться вкладку «Мережа», доки сторінка вантажиться. Усе, що там перелічено, і є тим, що отримує відвідувач. Прочитати це так займає кілька хвилин, і воно каже більше за вихідний код, бо це рівно той самий вигляд, який має стороння людина.