У багатьох команд є знайома схема: pull request із форка приходить у репозиторій, а робочий процес на pull_request_target одразу забирає код із цього PR. Це зручно, бо далі можна запускати перевірки, коментувати результат і навіть робити дії в репозиторії. Але саме тут і живе проблема: робочий процес уже має доступ до секретів, GITHUB_TOKEN базового репозиторію та середовища CI, а код при цьому приходить від зовнішнього контриб’ютора.
18 червня 2026 GitHub змінив поведінку actions/checkout v7: тепер він за замовчуванням відмовляється забирати небезпечний код із форка у сценаріях на кшталт pull_request_target і workflow_run. Це не косметична правка. Це зміна, яка змушує команду окремо вирішити, де у вас довірений код, а де недовірений код.
До змін
Ось типовий ризикований приклад:
name: pr-check
on:
pull_request_target:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
- run: npm test
На перший погляд це виглядає нормально: ми просто хочемо протестувати код із PR. Але в pull_request_target код запускається в контексті базового репозиторію. Якщо PR з форка змінить скрипти, workflow-файли або будь-яку логіку, що торкається секретів, наслідок може бути набагато гіршим за зіпсований білдів.
Після змін
Після оновлення checkout v7 відповідь GitHub проста: якщо робочий процес має привілейований доступ, не змішуйте його з checkout незнайомого коду за замовчуванням.
Практичний варіант виглядає так:
- Виконуйте перевірки коду форка в
pull_request, де немає доступу до секретів. - Використовуйте
pull_request_targetлише для безпечних дій над базовим репозиторієм. - Якщо привілейований доступ і checkout коду з форка все ж потрібні, зробіть це явним винятком після рев’ю.
name: fork-validation
on:
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: npm ci
- run: npm test
name: privileged-follow-up
on:
pull_request_target:
branches: [main]
jobs:
comment:
runs-on: ubuntu-latest
steps:
- run: echo "Safe repo-side action only"
Тут логіка проста: недовірений код перевіряється в непривілейованому середовищі, а привілейований робочий процес більше не мусить тягнути у себе зовнішній код лише заради зручності.
Що означає нова типова поведінка
actions/checkout v7 тепер не дає випадково зробити те, що раніше часто проходило “по звичці”. Якщо вам справді треба саме такий checkout, GitHub очікує явного opt-in через allow-unsafe-pr-checkout: true.
Це важливий сигнал для команди:
- якщо без цього прапорця робочий процес ламається, спочатку перевірте модель довіри;
- якщо робочий процес читає секрети, майже завжди краще розділити його на два етапи;
- якщо небезпечний checkout лишається, він має бути наслідком рішення, а не побічним ефектом.
Коли явне увімкнення ще може бути доречним
Є сценарії, де команда свідомо хоче checkout коду з форка у привілейованому робочому процесі. Наприклад, дуже специфічний DevEx пайплайн або внутрішня автоматизація з додатковими обмеженнями. Але навіть тоді варто пройти короткий чек:
- чи точно це завдання не може виконати те саме без checkout коду з форка;
- чи винесені секрети і write-операції в окремий крок;
- чи є ручне рев’ю або політика, яка має дозволити небезпечний режим перед увімкненням;
- чи задокументовано, чому цей виняток існує.
Якщо на ці питання немає чітких відповідей, типова поведінка GitHub тут допомагає не “стати менш зручним”, а не допустити типову помилку з надмірною довірою.
Швидке дерево рішень
Якщо вам треба вирішити, що робити з існуючим робочим процесом, почніть з трьох питань:
- Чи потрібні цьому завданню секрети або привілейований токен?
- Чи бере він код безпосередньо з форка?
- Чи можна розділити перевірку коду і привілейовану дію на два окремі потоки?
Якщо відповідь на перше “так”, а на друге “так” теж, це майже завжди знак, що робочий процес потрібно перепроєктувати. Якщо відповідь на перше “ні”, використовуйте менш привілейований тригер. Якщо відповідь на третє “так”, розділення є кращим за небезпечне явне увімкнення.
Що перевірити після міграції
Після переходу на v7 варто швидко підтвердити три речі:
- fork PR більше не отримує привілейований checkout випадково;
- довірений робочий процес не читає і не виконує недовірений код;
- усі винятки з
allow-unsafe-pr-checkoutописані та зрозумілі командам, що супроводжують репозиторій.
Висновок
GitHub не прибрав ваші можливості. Він просто прибрав випадковість.
Якщо ви і раніше будували pull_request_target обережно, v7 дає вам кращу типову поведінку. Якщо ж робочий процес був зібраний на “далі якось розберемося”, це саме той момент, коли варто зупинити автоматизм і відділити недовірений код від привілейованого доступу.
Далі почитати
Короткий чеклист
- Знайти всі кроки, яким потрібні секрети або право запису.
- Винести перевірку коду з форка в pull_request, якщо це можливо.
- Тримати привілейовані дії окремо від checkout коду.
- Вважати allow-unsafe-pr-checkout: true винятком, який потребує рев’ю.
- Перевірити, що процес після зміни відповідає правилам репозиторію.
План безпечної міграції з небезпечного fork checkout
Ти допомагаєш команді, яка вже використовує pull_request_target або workflow_run і інколи робить checkout коду з форка. Проаналізуй workflow і дай короткий план: 1. Які кроки тут належать до довіреного коду, а які до недовіреного коду? 2. Чи можна винести перевірку fork-коду в pull_request без секретів? 3. Якщо потрібен privileged job, які кроки треба відділити від checkout? 4. Коли явне увімкнення allow-unsafe-pr-checkout: true ще може бути виправданим? 5. Який мінімальний план переходу й перевірки допоможе не зламати CI? Поверни відповідь як практичний список дій для власника репозиторію або інженера, який відповідає за CI.