Semgrep налаштування: чому аналіз коду не ловить уразливості
Типова картина: Semgrep налаштування формально виконано — запуск у конвеєрі збірки є, звіт надходить, а користі з нього майже немає. Або спрацьовує все підряд, включно з фікстурами та прикладами з документації, або правил настільки мало, що вони мовчать на реальних проблемах. Команда швидко починає вважати такі перевірки формальністю.
Перший корінь — сам набір правил. Готові конфігурації не знають ваших домовленостей: як поводитеся з секретами, які обгортки над запитами використовуєте, де взагалі допустиме недовірене введення.
Правила аналізатора дають шум саме там, де контекст проєкту не враховано, і автор правки привчається закривати знахідку не читаючи.
Другий корінь — пороги та розбір спрацьовувань. Якщо кожне зауваження блокує збірку, у конфігурації з'являються винятки; якщо не блокує нічого, перевірки коду ігнорують.
Робоча схема — падати на нових знахідках у змінених рядках і тримати накопичений борг окремою чергою з зрозумілим власником.
Третій корінь — місце перевірки в процесі. Коли аналіз безпеки в конвеєрі збірки запускається тільки на головній гілці або раз на добу, зворотний зв'язок надходить через години після правки і вже не пов'язується з нею в голові автора. Статичний аналіз коду не працює не через слабкий інструмент, а через запуск для галочки.
Далі розбираємо, як це закривається крок за кроком: розмежування правил за зонами відповідальності, пороги на змінах, регулярний розбір знахідок і супровід конфігурації в актуальному стані.
Швидкість перевірок, шум у звітах, покриття правил
Повний прогін Semgrep по всій історії репозиторію триває десятки хвилин — і цю ціну розробник платить на кожній перевірці змін.
Ми налаштовуємо аналіз лише за зміненим кодом: скануються порушені та залежні файли, правила беруться з кешу, прогін стоїть обов'язковим кроком до злиття гілки. Перевірка змін займає пару хвилин і не вибиває інженера з контексту задачі.
Шум — головна причина, через яку команди вимикають сканер. Частка хибних спрацьовувань падає від конфігурації, а не від «магії»: точні шаблони замість широких виразів, явні пороги серйозності для блокуючих рівнів, винятки для генерованого коду та тестових даних.
Окремо ведемо базову лінію знахідок: збірка падає лише на нових дефектах, а успадковані йдуть у беклог з відповідальним.
Публічний набір правил закриває типові шаблони, але не знає про внутрішні бібліотеки та самописні обгортки доступу до даних.
Тому пишемо свої правила: обов'язкові перевірки прав перед запитом, функції очищення вхідних даних, заборона на складання запитів із користувацького введення. Покриття правил аналізу зростає від стандартного профілю до карти «який клас дефектів і де саме ми ловимо».
Ефект рахуємо за потоком знахідок: скільки підтверджено, скільки відхилено як хибні, які класи дефектів не доходять до релізу.
Ін'єкції в запити, небезпечна десеріалізація, ключі та токени, зашиті в код, перестають випливати на тестуванні на проникнення — вони блокуються під час злиття.
Режими сканування: конвеєр збірки, локальний запуск, розклад
Режими різняться не набором правил, а точкою запуску та обсягом перевірюваного коду. Одні й ті самі правила дають різний час відгуку та різне охоплення залежно від того, скануємо ми весь репозиторій чи лише дельту. Нижче — чим обмежений кожен варіант і на якому ешелоні він доречний.
| Режим | Коли доречний | Чим обмежений |
|---|---|---|
| Повний скан гілки в конвеєрі збірки | Захищені гілки та запити на злиття в основну | Час зростає з обсягом репозиторію: на великому монорепозиторії це десятки хвилин, тому тримаємо його лише на ключових гілках |
| Перевірка лише змінених файлів | Кожен коміт у робочих гілках | Не бачить проблем у коді, який не змінювався, і потребує коректної бази порівняння під час переписування історії |
| Локальна перевірка перед надсиланням | Хук перед комітом і ручний прогін перед надсиланням змін | Залежить від дисципліни та версії правил на машині розробника: розходження із сервером і обхід перевірки |
| Запуск за розкладом | Нічний повний прогін основної та довгоживучих гілок | Звіт надходить із затримкою і не блокує злиття; потрібен канал доставки та регулярний тріаж знахідок |
Ці режими не конкурують, а складаються в ешелони: швидкий відгук локально, блокуюча перевірка змін у конвеєрі, регулярний повний прогін за розкладом. Розробник отримує зворотний зв'язок до надсилання коду, а інфраструктура — гарантію, що покриття не деградує.
Перехід між режимами — правка однієї конфігурації, а не переписування правил: набір і пороги спрацьовувань залишаються спільними.
Semgrep налаштування: порядок робіт від аудиту до передачі
Порядок робіт будуємо так, щоб аналіз почав приносити користь до того, як стане обов'язковим кроком збірки. Спочатку інвентаризація та запуск у м'якому режимі, і лише після розбору знахідок правило переводиться в блокуюче. Інакше команда отримує сотні спрацьовувань першого ж дня і перестає дивитися на звіт взагалі.
- Аудит поточних правил. Вивантажуємо, що підключено зараз: які набори активні, що реально спрацьовує, що дублює лінтери та форматтери, які перевірки шумлять на легітимному коді.
- Схема запуску аналізу. Визначаємо точки входу — на кожній зміні, за розкладом на основній гілці, перед випуском версії — і що кешується між запусками, щоб розбір не подовжував збірку.
- Налаштування під проєкт. Вимикаємо шумні перевірки, піднімаємо пороги значущості, пишемо частину правил під внутрішні домовленості: робота із секретами, розбір вхідних даних, звернення до зовнішніх сервісів.
- Перевірка на історії змін. Проганяємо конфігурацію по минулих правках, а не лише по свіжому коду: так видно реальний обсяг знахідок і те, які правила дають хибні спрацьовування на вашій кодовій базі.
- Режим попереджень замість блокування. Перші проходи нічого не зупиняють: звіт збирається, знахідки розбираються, лічильник хибних спрацьовувань іде вниз. Блокування вмикається, коли частка достовірних знахідок це виправдовує.
- Регламент тріажу. Домовляємося, хто і в який строк дивиться звіт, як позначається хибне спрацьовування і як правило потрапляє у винятки — з обґрунтуванням, а не мовчки.
- Передача. Правила лежать у репозиторії поруч із кодом, схема запуску описана, у команди є порядок правки та зрозуміла точка входу.
Артефакти: конфігурації правил, схеми, регламент розбору знахідок
Після завершення робіт у репозиторії залишається не разове налаштування, а робочий контур аналізу, який команда замовника розвиває без нас. Усі артефакти версіонуються разом із кодом і проходять рев'ю як звичайні зміни — тоді видно, хто і навіщо правив перевірки.
- Набори власних правил під наш стек, розбиті за мовами та зонами відповідальності: обов'язкові для злиття та інформаційні. Кожне правило йде з прикладом «спрацювало — що робити» і перевіркою на тестовому наборі.
- Політика винятків і придушень: де ставиться придушення (у коді чи в конфігурації), хто погоджує, обов'язкові причина, власник і строк життя. Винятки без власника потрапляють в окремий звіт.
- Регламент розбору знахідок: які рівні критичності блокують злиття, які йдуть у чергу, хто ухвалює рішення «виправити / придушити / прийняти ризик» і як фіксується обґрунтування.
- Документація щодо запуску перевірок: прогін локально до коміту, звіт за гілкою, відтворення спрацьовування, тривалість повного проходу.
- Конфігурація вбудовування в збірку: кроки, кешування залежностей, паралельні завдання, режим падіння при нових знахідках.
- Базовий знімок поточних знахідок — увімкнення перевірок не блокує роботу команди першого ж дня.
- Метрики контуру: частка розібраних знахідок, число хибних спрацьовувань за кожним правилом, динаміка за критичністю.
Набір передаємо з коротким навчанням: інженери замовника проганяють його самі, а ми залишаємося на зв'язку щодо розвитку правил.
Кейс: частка хибних спрацьовувань і час перевірки до та після
Початкова точка
Проєкт — монорепозиторій з десятком сервісів і спільним конвеєром, аналіз коду увімкнули на правилах за замовчуванням. Після кожної зміни звіт приносив сотні зауважень, з яких підтверджувалися одиниці: частка хибних спрацьовувань трималася на рівні 71%.
Розбір звіту перед злиттям займав у середньому 45 хвилин, інженери почали пропускати перевірки і дивитися лише на статус збірки — захист формально працював, але нічого не ловив.
Що змінили
Semgrep налаштували під структуру репозиторію, а не навпаки. Правила розбили на набори: критичні (витоки секретів, ін'єкції, небезпечна десеріалізація) блокують злиття, решта йдуть у звіт без зупинки конвеєра.
Кастомні правила описали внутрішні обгортки доступу до даних, а тестові каталоги та згенерований код винесли у винятки. Додали порівняння з базовою гілкою — перевіряються лише змінені рядки, а не файл цілком.
Результат
Частка хибних спрацьовувань упала з 71% до 9%, і звіт знову стали читати цілком, а не вибірково. Час перевірки змін скоротився з 45 хвилин до 7, при цьому жодна критична знахідка не загубилася: їх ловлять на етапі перевірки, а не на проді.
Через кілька тижнів команда перестала сперечатися про шум і зайнялася розвитком правил — новий набір під сервіс додається за один прохід.
Чим штатні правила відрізняються від власних і коли потрібні обидва
Готовий набір Semgrep закриває типові класи уразливостей: ін'єкції, слабку криптографію, секрети в репозиторії, небезпечні виклики популярних бібліотек. Знахідки з'являються з першого прогону — правила спираються на загальні сигнатури мови, а не на структуру вашого коду.
Власні правила під проєкт описують специфіку архітектури: обов'язковий виклик обгортки замість прямого запиту до бази, перевірку прав в обробнику, заборону на внутрішній модуль із відомою слабкістю. Вони прив'язані до імен ваших сутностей, тому чужий проєкт їх не підхопить.
| Набір | Коли підходить | Обмеження |
|---|---|---|
| Штатний | Перший прогін, зовнішні залежності, типові помилки | Не бачить внутрішніх домовленостей, шумить на безпечних для вас конструкціях |
| Власний | Свій шар доступу до даних, обов'язкові перевірки прав | Потребує супроводу: після рефакторингу шаблони треба переперевіряти |
| Обидва разом | Продукт із власною архітектурою та зовнішніми залежностями | Потрібна пріоритизація, інакше потік знахідок змішується і розбір розтягується |
Суміщення наборів дає повну картину: штатний закриває зовнішній контур, власний — внутрішні домовленості команди.
Пріоритизація йде за джерелом знахідки: спрацьовування свого правила майже завжди означає порушення вашої ж домовленості про код, тоді як попередження штатного частіше потребує перевірки контексту.
Межа проходить за простим питанням: чи спрацює правило в незнайомому проєкті тією ж мовою? Якщо так — це штатний набір; якщо воно спирається на ваші модулі — власний. Обидва разом закривають і загальний фон, і специфіку архітектури проєкту.
Обмеження та типові питання перед впровадженням
Аналіз коду на етапі збірки не замінює динамічне тестування та ручний розбір: він бачить потік даних усередині файлів і модулів, але безсилий проти прав доступу, конфігурації середовища та логіки, яка проявляється лише під навантаженням.
Тому перевірки вбудовуємо як один із шарів — поруч із контролем залежностей і пошуком секретів. Нижче — сумніви, які команда замовника піднімає найчастіше до старту робіт.
Окрема тема — супровід. Свої правила в Semgrep живуть як код: у них є власник, тести на прикладах спрацьовувань і прогін при оновленні движка. Без цього через пару місяців набір перетворюється на звалище, яке вимикають цілком — разом із корисними перевірками.
Хибні спрацьовування паралізують роботу команди?
Знімаємо три причини шуму: будуємо базову лінію за поточним станом репозиторію і не блокуємо те, що було раніше; вмикаємо перевірку лише на змінених рядках; задаємо поріг за рівнем критичності для блокування, решта йде у звіт.
Придушення оформлюємо анотацією з обґрунтуванням і строком перегляду. Частку хибних спрацьовувань рахуємо на тижневих тріаж-сесіях — це вимірювана величина, а не відчуття.
Що буде при оновленні правил або движка?
Набори версіонуються разом із кодом, нова ревізія спочатку проганяється на еталонній гілці й порівнюється з попереднім результатом за кількістю знахідок. Якщо різниця пояснювана — вмикаємо, якщо ні — правило доопрацьовується. Перший прогін після оновлення йде в режимі попереджень, збірка не падає.
Чи можна впроваджувати поетапно, без зупинки релізів?
Так, і це бажаний шлях: один-два сервіси в режимі спостереження, потім блокування на змінених рядках, потім розширення на решту репозиторіїв. Порядок етапів фіксуємо заздалегідь, щоб команда бачила, коли перевірки почнуть впливати на збірку, і встигла розібрати накопичене.
З чого почнемо роботу за вашим репозиторієм
Щоб старт робіт за репозиторієм займав дні, а не тижні, нам потрібен від вас мінімальний набір вхідних даних і одна коротка розмова по суті. Список нижче — те, що запитуємо на обговоренні задачі; він же стає каркасом плану впровадження перевірок.
- Доступ до коду: репозиторій або його дзеркало з історією комітів — без неї не побудувати базовий зріз і не відокремити нові знахідки від тих, що живуть у кодовій базі давно. Для монорепозиторію — розбивка за каталогами та власниками модулів.
- Доступи до систем збірки: право завести окремого сервісного користувача і додати крок аналізу, але без прав на зміну логіки релізів.
- Точки інтеграції: що має запускати перевірку — коміт, запит на злиття, нічний прогін за повною історією. Від цього залежить, де ставимо блокуючі пороги, а де лише звіт.
- Чинні правила та винятки: які лінтери й аналізатори вже працюють, де зберігаються придушення, хто їх погоджує. Дублювати наявні перевірки сенсу немає.
- Пріоритети за класами знахідок: які категорії для вас критичні, що йде в ігнор (тести, згенерований код, сторонні вендорські каталоги). Це прямо впливає на обсяг кастомних правил.
- Відповідальний за тріаж з боку замовника: один інженер, який розбирає знахідки і вирішує, що йде в роботу, а що у виняток.
Після цього ми повертаємося з оцінкою та планом: етапи, обсяг кастомних правил для Semgrep, цільовий рівень шуму та метрики, за якими будемо перевіряти результат. Опишіть задачу — почнемо з розбору репозиторію.







