Перейти до вмісту

Чи безпечний ваш застосунок на Windsurf?

Чи годиться Windsurf для живого застосунку? Згенерований код зазвичай нормальний. Прослизає та зміна, якої ніхто не читав, у файлі, який ніхто не відкривав.

Vlad Tkachenko4 хв читання
Картка перевірки безпеки Reeve для застосунків на Windsurf, з логотипом Windsurf на білій плитці.

Логотипи належать їхнім власникам і показані, щоб позначити сумісність.

Коротко

  • Застосунок на Windsurf з боку коду зазвичай безпечний. Прослизає та зміна, якої ніхто не читав, тож перевіряйте результати, а не діфи.
  • Пошукайте service_role і sk_live_ у результаті свого складання. Це охоплює кожен файл, якого торкнувся помічник, хоч ви його відкривали, хоч ні.
  • Row Level Security є єдиною перевіркою, що переживає код, якого ви ніколи не читали, бо кожен запит мусить пройти через базу даних.

Windsurf може змінити багато у вашому проєкті за один крок: кілька файлів, міграцію, конфігурацію – усе разом і все робоче. Результат зазвичай хороший. Проблема в перегляді: зміну, розкидану по багатьох файлах, не читають так, як читають зміну в одному, а ті дві речі, які варто спіймати, мають по одному рядку.

Ось що гайд за гайдом подає неправильно: відповідь не в тому, щоб читати уважніше. На швидкості, з якою працюють ці інструменти, уважне читання не масштабується. Масштабується перевірка двох результатів, які важать: ззовні й постфактум.

Половина вашого застосунку, публічна за будь-яких обставин

Увесь його фасад.

Уявіть крамницю. Усе, що Windsurf будує у ваш інтерфейс, є вітриною, і вітрину цілком вручають кожному відвідувачу: браузер не покаже сторінки, якої йому не надіслали. За нею стоїть склад, ваша база даних, окрема будівля в інтернеті з власною адресою й власним замком.

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

Чи проблема, що в бандлі вашого застосунку на Windsurf є ключ?

Зазвичай ні. Залежить від того, який саме, а ці два майже не відрізняються.

Обидва звуться API-ключами. Лише один із них будь-коли призначався для читання.

Публічний ключ називає ваш проєкт і більше нічого не робить: sb_publishable_… у нових проєктах Supabase, anon у старіших. Його призначено для читання, і знайти його не знахідка. Секретний ключ, sb_secret_… або старіший service_role, обходить кожне написане вами правило й читає та змінює кожен рядок у кожній таблиці.

Те, як з'являється другий, варто знати, бо це не недбалість. Помічник, якого просять змусити браузерний компонент говорити з вашою базою, пише код, що працює, і якщо цьому коду потрібен секретний ключ, ключ вирушає туди, де код виконується. Vite прямо каже, що значення з префіксом VITE_ пакується у ваш вихідний код під час складання; Next.js робить те саме з NEXT_PUBLIC_. Ніщо вас не попереджає, бо з погляду інструмента ви попросили саме про це. Прочитати, який у вас ключ займає приблизно хвилину.

Єдине правило, що переживає код, якого ви не читали

Row Level Security, якщо ваші дані в Supabase, є перемикачем для кожної таблиці, який рядок за рядком вирішує, кому що читати.

Ваш застосунок і сторонній стукають в одні й ті самі двері. Хто увійде, вирішує налаштування, а не екрани вашого застосунку.

Саме тому це та перевірка, яку варто робити. Кожен запит доходить до бази даних, хоч би з якого файлу він прийшов і хоч би хто той файл написав. Правило, застосоване там, діє на всі одразу, включно з кодом із тієї зміни, яку ви лише перебігли очима. Жодна кількість непереглянутого коду не змінює того, що отримує назад неавтентифікований запит.

Дві речі вирішують, чи є вона у вас. Supabase вмикає Row Level Security за замовчуванням для таблиць, створених у Table Editor панелі, і не вмикає для створених виконанням SQL, а саме так їх створює згенерована міграція. І перемикач це лише половина справи: політика, яка дозволяє всім, лишає таблицю відкритою, доки панель звітує про неї як про захищену.

Як перевірити власний проєкт на Windsurf приблизно за десять хвилин

Шукайте у результаті складання, а не у вихідному коді. Зберіть проєкт, а потім пошукайте у вихідних файлах service_role, sb_secret_ і sk_live_. Одна команда, і вона охоплює кожен файл, якого торкнувся помічник, хоч ви його відкривали, хоч ні.

Прочитайте змінні з префіксами. Усе, що зветься VITE_… чи NEXT_PUBLIC_…, є опублікованим. Про кожну спитайте себе, чи поклали б ви її на головну сторінку.

Відкрийте в Supabase Authentication → Policies. Будь-яка таблиця, у списку якої Row Level Security вимкнена, відповідає кожному, у кого є адреса вашого проєкту, а ця адреса у вашому застосунку.

А потім подивіться ззовні. Три перевірки вище кажуть, що налаштовано. До чого справді дістається сторонній, лишається іншим питанням, і саме на нього відповідає наше безкоштовне сканування: воно читає ваш живий сайт як відвідувач і дає оцінку приблизно за 20 секунд, без акаунта: сканувати застосунок.

Що робити

  • Переглядайте за результатом, а не за діфом. На такій швидкості читати кожен змінений рядок не план.
  • Відвантажується зібраний бандл. Шукати в ньому швидше й правдивіше, ніж читати вихідний код, з якого він постав.
  • Публічний ключ у браузері доречний. sb_secret_… і service_role варто замінити.
  • Помічник кладе ключ туди, де він потрібен написаному ним коду. Тримати ключ поза браузером ніколи не було частиною запиту.
  • Row Level Security і є тією перевіркою, що переживає код, якого ви ніколи не читали, бо кожен запит мусить пройти через базу даних.

Зберіть проєкт і пошукайте в результаті service_role та sk_live_, і це хвилина й однозначна відповідь щодо тієї зміни, якої ви не читали. Далі 10-хвилинний чекліст безпеки охоплює решту.

Що насправді може піти не так із застосунком, зробленим у Windsurf

Ніщо з цього не означає, що ви зробили щось не так: це звичайні побічні ефекти того, що агент швидко пише багато коду. Ось що варто перевірити:

  • Секретний ключ, який агент підключив за вас

    Щоб інтеграція запрацювала з першого разу, агент іноді вписує ключ просто в код, і якщо цей файл виконується в браузері, його може прочитати будь-хто. Деякі ключі й мають бути публічними, і це нормально. Reeve читає завантажений код вашого застосунку, знаходить ключі й каже, які з них безпечні, а які треба перенести на сервер.

  • Закомічений .env або відкрита папка .git

    Ключі мають лежати у файлі .env, який ніколи не виїжджає у продакшн. Але зміну на десятки файлів легко підтвердити, не читаючи всіх шляхів у ній: .env таки потрапляє в коміт, або прихована папка .git потрапляє в деплой, і вся ваша історія разом із ключами опиняється за одне завантаження. Reeve перевіряє, чи доступне щось із цього ззовні.

  • Відкрита база даних (RLS вимкнено)

    Якщо застосунок зберігає дані (зазвичай у Supabase чи іншому Postgres), саме Row Level Security вирішує, хто може читати чи змінювати кожен рядок. Вимкнути її – швидкий спосіб змусити щось працювати під час розробки, і так вона часто й лишається. Reeve перевіряє це, рахуючи рядки, і ніколи їх не читає.

  • Публічне сховище файлів

    Завантажені файли лежать у "бакетах" сховища, і публічний бакет дозволяє будь-кому переглянути список і завантажити те, що всередині: рахунки, документи, приватні фото. Reeve перевіряє, чи можна отримати список ваших бакетів; він ніколи не завантажує чужі файли.

  • Увімкнені source maps

    Source map віддає кожному, хто зазирне, читабельну копію вашого початкового коду. Під час розробки це зручно, а в продакшні це подарунок незнайомцю, бо так легше знайти будь-яку іншу прогалину. Reeve перевіряє, чи не поїхали ваші разом зі збіркою.

  • Відсутні захисні заголовки та відкриті ендпойнти

    Кілька налаштувань підказують браузеру, як захищати ваших відвідувачів; окремим питанням є те, чи відповідають ваші ендпойнти даних будь-кому й з будь-якого сайту. Поодинці це дрібниці; разом вони визначають, що незнайомець зможе зробити зі знайденим. Reeve покаже, чого бракує.

Що таке Reeve і чим він не є

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

Windsurf є редактором, а не хостингом: він пише й виконує код разом з вами, але не публікує ваш застосунок і не стежить за ним потім. Ця частина лежить на вас і на тому, що створив агент. Найкраща звичка тут: переглянути велику зміну, перш ніж її прийняти; а якщо ви користуєтесь Supabase, його власний advisor вкаже на проблеми з базою. Reeve додає погляд ззовні: що насправді відкриває опублікований застосунок, зрозумілими словами, з якими можна щось зробити. А якщо не хочете про це думати, ми поспостерігаємо за вас.

Хочете, щоб цим займалися, а не лише перевірили?

Reeve Care продовжує стежити за вашим застосунком, робить резервні копії даних і допомагає полагодити, коли щось ламається, щоб ви могли будувати далі, а не хвилюватися.

Дізнатися про Reeve Care

Поширені запитання

Чи безпечний код, який пише агент Windsurf?

Часто це хороший код, але "його написав агент" не означає "хтось перевірив його на безпеку". Агентні зміни оптимізують результат, який працює, а заради цього ключ інколи опиняється не там або правило бази вимикають, щоб обійти помилку. Дізнатися напевно можна лише подивившись, що відкрито. Reeve робить це безкоштовно приблизно за 20 секунд.

Cascade змінив багато файлів одразу. Як зрозуміти, що відкрилося?

Читанням здебільшого ніяк. Це чесна відповідь, і саме тому допомагає погляд ззовні: замість перевіряти дифи, Reeve дивиться на застосунок, який ви справді опублікували, і повідомляє, до чого може дістатися незнайомець: ключі в браузері, відкрита база, файли для завантаження, відкритий .env.

Як дізнатися, чи не витікають API-ключі з мого застосунку на Windsurf?

Найчастішою причиною є ключ у коді, який виконується в браузері, де "приховано" не існує. Reeve читає завантажений код вашого застосунку, знаходить ключі й каже, які можуть бути публічними, а які треба перенести на сервер, і ніколи не зберігає справжні значення.

Чи змінить щось сканування мого застосунку на Windsurf?

Ні. Reeve дивиться лише на те, що вже й так публічно доступне ззовні. Він ніколи не входить в акаунт, нічого не змінює й не завантажує ваші файли. Лише читання, наче перевірити, чи замкнені двері, не заходячи всередину.

Агент змінив файли, які я ніколи не відкривав. Як мені це переглядати?

Не рядок за рядком, і це чесна відповідь. Переглядайте за результатом: зберіть проєкт і пошукайте у результаті форми секретних ключів, а потім подивіться, що ваша база даних повертає на запит без входу. І те, і те займає хвилини, і обидва ловлять ті дві поразки, які справді важать, байдуже, скільки файлів змінилося.

Чи кладе помічник зі ШІ секрети в мій фронтенд навмисне?

Він кладе їх туди, де вони потрібні написаному ним коду. Якщо компонент, що виконується у браузері, написали так, аби він викликав щось, що вимагає секретного ключа, ключ мусить бути у браузері, щоб цей код працював, тож помічник робить так, щоб він працював. Вказівки лишити ключ на сервері в запиті не було.

Яка одна перевірка каже мені найбільше про мій застосунок?

Чи ввімкнена Row Level Security для кожної таблиці й чи справді політики когось обмежують. Це єдине правило, що діє для кожного запиту, з якого б файлу він не прийшов, і тому воно переживає будь-яку кількість коду, якого ви не читали.

Автор

Vlad Tkachenko

Засновник Reeve

Я щодня дивлюся на застосунки, зібрані в Lovable, Bolt, v0, Cursor і Replit, і на короткий список помилок, які трапляються в них знову і знову.

Більше про автора

Будували деінде? У нас є такий самий чесний розбір для:

← Усі гайди з безпеки конструкторів

Автоматична зовнішня перевірка, а не повний аудит. Відсутність знахідок не є гарантією безпеки.