1. Deny-rule зупинить команду. Ваш copy-paste — ні
Allow/ask/deny rules і protected paths на кшталт payments/** та .env* уже закрили один біль: Claude не ходить вільно по чутливих зонах репозиторію. Здається, після цього можна видихнути — але є неприємний момент: deny-rule зупиняє команду, а ваш власний copy-paste в prompt — ні. Саме тут і починається сьогоднішня тема. Коли ми говоримо про безпеку AI-workflow, дуже легко думати лише в термінах команд: що Claude запустить, відредагує, куди піде. Це важливо, але це лише половина картини. Друга — який матеріал ви самі приносите в сесію. Token, customer email, сирий production-log, експорт support ticketʼа, вставлені вручну, — проблема сталася раніше за будь-який tool call.
Тут корисно тримати в голові просту формулу:
Permissions обмежують дії Claude, а гігієна даних обмежує матеріал, який ви самі вносите в контекст.
Це два різні шари. Але ні CLAUDE.md, ні deny-rule не фільтрують буфер обміну — вставили зайве, значить свідомо. Claude Code, як дуже чесний стажер, не скаже: «Я бачу, у вас тут випадково живий Stripe key, давайте я відвернуся». Він це прочитає, врахує і, можливо, включить у summary.
Через це навіть на перший погляд безневинна задача може різко стати ризикованішою. Оновлення документації зазвичай тягне лише на low-risk. Але вставте в сесію production-логи з email клієнтів, внутрішні URL і сліди токенів — і це вже не «просто про README». Ризик визначає не вид роботи, а якість даних.
І ще один важливий нюанс. Багато хто думає про чат як про розмову «тут і зараз» — але в Claude Code це не просто розмова, а ланцюжок артефактів: transcript, tool outputs, file snapshots, exported notes, generated docs, іноді screenshots і handoff notes. Ви розмовляєте не лише з моделлю, а й із майбутньою стенограмою цієї бесіди. А стенограма живе довше, ніж вам хотілося б.
2. Секрети починаються раніше, ніж sk_live_...
Коли чуєш слово secrets, мозок одразу малює паролі та API-ключі. Картинка правильна, але занадто вузька. У реальному проєкті чутливі дані починаються задовго до рядка sk_live_... і закінчуються значно пізніше — особливо там, де є гроші, користувачі та support, як у нашому Commerce OS. Корисніше дивитися не на один тип сутностей, а на кілька робочих категорій.
| Категорія | Приклад у Commerce OS | Чому не можна вставляти як є | Чим замінювати |
|---|---|---|---|
| Секрети | , , |
Дають прямий доступ до системи або оточення | .env.example, імʼя змінної, маскування значення |
| Персональні дані | email, телефон, адреса, повна історія замовлень клієнта | Ідентифікують людину та тягнуть за собою приватність | маскування, синтетичний клієнт, знеособлений кейс |
| Операційні дані | внутрішні URL, Sentry-посилання, trace id, заголовки з токенами | Розкривають внутрішній периметр і сервісні звʼязки | короткий відрізок без хостів, токенів і зайвих ідентифікаторів |
| Фінансові та бізнес-дані | точні суми повернень, маржа, внутрішні правила знижок | Комерційно чутливі, іноді повʼязані з клієнтом | синтетичні значення зі збереженням логіки порогів |
| Артефакти підтримки | сирі support tickets, скріни адмінки, експорт переписки | Зазвичай містять одразу все погане: і PII, і гроші, і внутрішні деталі | переписаний підсумок, обрізаний і замаскований скрин |
Тут є тонка, але дуже важлива думка. «Синтетичні значення» — не «будь-які випадкові числа». Баг проявляється лише для повернень вище 100 USD — не можна замінити 149.00 на 9.00: сенс кейсу помре. Помилка про перехід дати через північ в іншому часовому поясі — не можна замінити проблемний timestamp на спокійну дату посеред дня. Хороша sanitization зберігає логіку проблеми, погана робить усе безпечним і безкорисним.
Тому краще думати так: ви не ховаєте правду, ви ховаєте зайву ідентифікацію. Потрібен факт, що сума була вище порогу, — а не те, що клієнт Іван Петров отримав refund на 149.37 USD за замовленням ORD-938221-AZ. Для розслідування важливі поріг і перехід стану, а не доля бідного ORD-938221-AZ. Усе просто: чутливі дані — це все, що допомагає дізнатися хто, де, з чим саме і як влаштовано всередині, коли для задачі достатньо знати лише який механізм зламався.
3. Витік розповзається по дрібницях
Коли кажуть «не вставляйте секрети в промпт», це звучить правильно, але трохи наївно. У реальній роботі дані рідко витікають одним красивим рухом через велику вставку. Частіше розповзаються по дрібницях: шматок потрапив у командний вивід, інший — у screenshot, третій — у handoff note, четвертий — у summary від subagentʼа. Ніхто наче нічого жахливого не зробив, а витік уже стався. Зручно дивитися на це як на набір поверхонь, з якими ви працюєте щодня.
| Поверхня | Як виглядає витік | Чому це небезпечно | Безпечна заміна |
|---|---|---|---|
| Prompt / task spec | вставили сирий support ticket або .env | дані одразу стають частиною контексту | переписаний summary, .env.example |
| Вивід команди | cat .env, повний curl -v, сирий лог із production | потрапляє в transcript і summary | короткий відрізок без секретів і зайвих заголовків |
| Transcript / export сесії | надіслали ревʼюеру або в чат команди «як є» | зберігає все, що вже пролетіло через сесію | знеособлений експорт або ручний summary |
| Generated docs / notes | Claude вставив реальні значення в README, EVIDENCE_LOG, PR notes | чутливі дані переїжджають у файл з довгим життєвим циклом | фінальний ручний review артефактів |
| Скріншоти | видно адмінку з email, адресами та order history | картинка теж артефакт, а не “просто картинка” | crop, blur, synthetic demo screen |
| Summary subagentʼа | subagent прочитав небезпечні дані, потім переповів їх main session | main session успадкувала експозицію | subagent теж отримує лише знеособлені дані |
Дуже типовий антиприклад виглядає так:
cat .env # Погано: реальні ключі потраплять у вивід команди і в transcript
cat .env.example # Добре: структура конфігурації зрозуміла, секретів немає
Тут проблема не в команді як такій. Проблема в тому, що вивід команди — це теж контекст. А отже, якщо ви один раз показали моделі реальний .env, подальший /clear уже не чарівна гумка. Він очищує поточний діалоговий шар, але не скасовує того факту, що ви вже створили локальні артефакти, могли експортувати сесію, переслати summary або зафіксувати цю інформацію в нотатках.
Те саме стосується generated docs. Дуже підступний сценарій: ви скормили Claude Code сирі дані «на хвилинку», а потім попросили зробити EVIDENCE_LOG.md або REVIEW_NOTES.md. Модель, як дисциплінований помічник, чесно включила туди те, що визнала важливим. У цей момент витік перестає бути «десь у чаті» і стає звичайним файлом у репозиторії або робочій папці.
Окремо запамʼятайте одну неприємну річ про subagentʼів. Ізоляція контексту — це не магічна дезінфекція. Якщо subagent прочитав чутливі дані, його summary теж стає чутливим матеріалом. Тобто subagent чудово ізолює міркування, але не перетворює сирий production log на безпечний. Було б зручно, звісно, але, на жаль.
4. Санітизація, яка не вбиває доказ
Слово sanitization іноді звучить так, ніби зараз почнеться ритуальна бюрократія. Насправді це дуже інженерна практика. Ваше завдання — прибрати все зайве, але зберегти ті властивості даних, без яких баг, перевірка або аналіз втратять сенс. Якщо зробити занадто мʼяко, залишаться ризики. Якщо зробити занадто агресивно, ви вбʼєте корисну інформацію. Це майже як рефакторинг: змінюємо форму, намагаючись зберегти потрібну поведінку.
Найпрактичніший спосіб — перед підготовкою контексту поставити собі три запитання. По-перше, що саме в цих даних важливе для задачі. По-друге, які поля лише ідентифікують користувача або систему, але не впливають на сам механізм. По-третє, які відношення між значеннями треба обовʼязково зберегти: пороги, формат ID, послідовність подій, різницю в часі, стан до і після.
Наприклад, для бага з поверненнями важливе не прізвище клієнта, а факт, що повернення було вище порогу і перейшло не в той стан. Тому замість сирого ticket краще передавати моделі ось такий summary:
## Підсумок щодо проблеми з поверненням
Order id: ORDER-****-2048
Customer: existing_user_01
Refund amount: 149.00 USD
Observed behavior: status changed from `PENDING` to `APPROVED`
Expected behavior: refunds above `100.00 USD` must stay `PENDING_APPROVAL`
Environment: відтворення в production-подібному середовищі на знеособленому наборі даних
Зверніть увагу: тут збережені всі механічно важливі властивості кейсу. Сума й досі вище порогу. Назви станів збережені. Є натяк на середовище. Але зникли email, адреса, точний реальний order id, платіжний ідентифікатор і все, що робить кейс упізнаваним на рівні клієнта.
Те саме стосується логів. Погана sanitization часто виглядає як «замінемо все на ***». У результаті модель бачить незрозумілу кашу. Набагато корисніше залишити структуру логу, але прибрати ідентифікацію:
2026-05-12 10:14:33 WARN RefundPolicyChecker
orderId=ORDER-****-2048 customerEmail=<masked@example.com>
amount=149.00 USD threshold=100.00 USD
actualState=APPROVED expectedState=PENDING_APPROVAL
Такий лог і далі допомагає розслідувати проблему. Видно, який компонент спрацював, який стан був фактично, який очікувався, на якому значенні спрацював поріг. Але він уже не тягне за собою зайве життя клієнта.
Дуже часта помилка — замаскувати значення, але не зберегти формат. А формат іноді й є половиною бага. Якщо у вас помилка виникає лише на довгих order id або на конкретному timezone-переході, цю властивість треба зберегти і в знеособленому прикладі. Тобто ORDER-****-2048 краще, ніж просто 123. А timestamp, який перетинає межу дати, корисніший, ніж вичищений «нейтральний» рядок без часового контексту.
Скріншоти підпорядковуються тій самій логіці. Якщо ви показуєте моделі або колезі екран адмінки, то crop і blur — не косметика. Це спосіб не тягнути email, адресу, номер замовлення і список попередніх покупок, коли для обговорення потрібен лише один блок зі статусом повернення. У screenshotʼа рівно такий самий статус артефакту, як у markdown-файла. Він не стає безпечним лише тому, що у форматі PNG.
5. Правило, а не одноразове осяяння
На цьому етапі важливо перейти від «я зрозумів думку» до «у мене це зафіксовано в процесі». Бо одноразове осяяння живе приблизно до першого дедлайну. А потім починається старе добре «та ну, один раз вставлю». Саме тому в Workflow Kit правила про чутливі дані краще оформлювати як артефакти, а не тримати лише в голові.
Почати варто з простого: CLAUDE.md і CLAUDE.local.md — не місце для секретів. Узагалі. Ні «тимчасовий test key», ні «швидкий доступ до staging DB», ні «про всяк випадок покладу токен». Ці файли підтягуються в сесії знову і знову. Покласти туди секрет — це все одно що приклеїти його на монітор, тільки ще й зручніше для моделі.
Набагато корисніше винести правило в окремий rule-файл всередині Workflow Kit. Наприклад, так:
# rules/no-secrets-in-prompts.md
Не вставляй у prompts, task spec, notes і examples реальні API keys, tokens,
паролі, вміст `.env`, email клієнта, телефон і адресу.
Користуйся `.env.example`, масками і знеособленими підсумками.
Якщо секрет уже потрапив у вивід команди, вважай його скомпрометованим:
зупинися, заміни секрет і не поширюй вихідний transcript далі.
Цей фрагмент корисний одразу з кількох причин. По-перше, він короткий. По-друге, він не намагається бути курсом із compliance. По-третє, у ньому є не лише заборона, а й безпечна заміна: .env.example, маски, підсумки. Тобто правило не просто каже «не можна», а ще й показує нормальний маршрут.
Далі має сенс закріпити це в робочих файлах, які люди реально відкривають. Наприклад, у CLAUDE.md проєкту можна спокійно залишити такий розділ без жодних секретів:
## Робота з конфігами та логами
Використовуй `.env.example`, а не `.env`.
Для розбору помилок вставляй лише знеособлені логи.
Не включай customer data і реальні identifiers у notes, docs та review artifacts.
Якщо не впевнений — спочатку знеособ дані, потім віддавай їх у сесію.
Зверніть увагу: тут немає enforcement у технічному сенсі. І це нормально. CLAUDE.md нагадує намір, а rules, hooks і review утримують дисципліну. Саме ця звʼязка і робить процес живим. Бо одна лише інструкція швидко забувається, а одні лише deny-правила не розвʼязують проблему ручного copy-paste.
Окремо стежте за evidence-файлами. EVIDENCE_LOG.md, REVIEW_NOTES.md, PR_DESCRIPTION.md, HANDOFF_NOTE.md і навіть звичайний коментар у командному чаті часто стають місцем вторинного витоку. Ви вже все правильно знеособили в prompt, але потім попросили Claude зробити гарний summary і забули його перечитати. У результаті чутливі значення повертаються через бічні двері. Тому generated docs у таких темах завжди потребують ручного фінального читання очима, а не лише довіри diffʼу.
І так, subagent тут теж не імунітет. Якщо reviewer-agent або debugger-agent отримав небезпечний контекст, його вивід треба ревʼюити так само суворо, як і свій власний. Subagent — це не хімчистка для секретів. На жаль. Було б дуже зручно, але довелося б читати менше лекцій, а це вже підозріло.
6. Розслідуємо баг повернень без витоку
Щоб усе це не залишилося красивою теорією, давайте складемо реальний сценарій. Уявіть, що в Commerce OS надійшов сигнал: повернення вище 100 USD іноді проходять без ручного підтвердження. Сама по собі задача явно review-required, бо зачіпає гроші та flow повернень. Але якщо ви ще й почнете годувати Claude сирими production-даними, ви швидко скотитеся до high-risk поведінки вже на рівні контексту.
Правильна робота починається не з «скину-но я весь лог». Вона починається з підготовки безпечного пакета доказів. Ви берете реальний кейс, вручну виймаєте з нього лише значущі властивості й перетворюєте все це на короткий sanitized summary. Потім додаєте мінімальний лог-відрізок, де видно стани й поріг, але не видно клієнта, токена, внутрішнього host name і платіжного ідентифікатора. І лише після цього йдете в Claude Code.
Гарний дослідницький запит у такій ситуації може виглядати так:
Досліди баг із поверненнями в Commerce OS.
Використовуй лише знеособлені дані з цього task spec.
Не читай `.env` і не проси повний production log.
Зосередься на логіці порогу повернення та переході станів.
Поверни:
1. ймовірну причину;
2. файли, на які це впливає;
3. кроки локальної перевірки;
4. що ще потрібно підтвердити вручну.
Зверніть увагу: такий prompt не робить вас біднішими в розслідуванні — він дисциплінує аналіз. Ви не завалюєте модель сміттям, не створюєте новий ризик і отримуєте структурований результат. А якщо пізніше знадобиться handoff note для колеги, у вас уже є знеособлений матеріал, який не страшно передати далі.
Саме в таких робочих звичках і проявляється зрілість AI-native engineering. Не в тому, що ви знаєте модне слово sanitization, а в тому, що перед кожним багом автоматично ставите собі запитання: «Що тут справді потрібно для аналізу, а що я зараз збираюся тягнути по інерції?» За якийсь час це перестає відчуватися як додаткова бюрократія і починає працювати як звичайна інженерна гігієна — приблизно як перевірити diff перед commit. Тільки тут ви перевіряєте не код, а сліди даних, які цей код і ваша сесія залишають довкола себе.
7. Хмарні планувальники розширюють поверхню витоку
Окремо варто сказати про хмарні поверхні Claude Code, бо вони помітно розширюють поверхню витоку даних. Хмарний планувальник і хмарне ревʼю (умовно /ultraplan, /ultrareview або їхні аналоги — точна назва й доступність можуть змінюватися від версії до версії) працюють не на вашій машині: вихідний код, diff і контекст файлів передаються в хмарне середовище й потрапляють у його транскрипти, логи та записи обліку витрат.
Порівняно з локальною сесією це розширює поверхню для чутливих даних, і ставитися до хмарного агента варто рівно так само, як ми домовилися ставитися до prompts: усе, що надіслано, вважається потенційно розкритим.
Практичні правила тут звучать нудно, але саме ця нудьга і є профілактикою витоків. Репозиторій, гілка або diff, які ви надсилаєте в хмарного агента, не мають містити секретів у відкритому вигляді, персональних даних клієнтів, підписаних assetʼів або продакшн-доступів в історії комітів. Перед запуском такої команди корисно явно перевірити, які файли потрапляють у контекст — часто це вся гілка разом із метаданими репозиторію та залежностями, — і пройтися підозрілими масками: .gitignore, secret, .env*, *credential*, *key*.
Регульовані середовища — HIPAA, PCI-DSS, FedRAMP, дані з вимогою on-prem-only — з хмарними поверхнями зазвичай несумісні за вимогами відповідності, і там безпечніше залишатися на локальних subagentʼах і плагінах. Слід аудиту хмарної сесії — що надіслано, що отримано, ким запущено — має бути доступний власникові команди, інакше сліду для перевірки відповідності просто не існує, а це сам по собі стопор у регульованому середовищі. І, нарешті, вивід хмарного агента — розмічений diff, план, знахідки — це теж поверхня витоку: не публікуйте його у відкритих артефактах без очищення.
Але навіть ідеально знеособлений контекст не відповідає на інше запитання: де взагалі має жити ризикований експеримент. Коли дані вже очищені, наступний шар захисту — пісочниця, а не героїзм в основній робочій копії.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ