Все записи
6 мин

Я вставил рабочий API-ключ прямо в чат с нейросетью — и чем это плохо кончается

безопасностьвайбкодингclaude code

Если вы засветили рабочий API-ключ, и неважно куда вы его засунули, в чат, в коммит, в скриншот, то правильный порядок действий ровно один. Немедленно идёте в кабинет провайдера, отзываете этот ключ, выпускаете новый и кладёте его в `.env`, который у вас лежит в `.gitignore`. Не «потом поправлю», не «да там же только я», а прямо сейчас, потому что ключ, который один раз вылетел из защищённого места, надо считать скомпрометированным, и точка. Я это пишу не из методички, а потому что сам на днях так влетел, когда торопился завести проект и решил, что чуть-чуть срезать угол не страшно.

Как я вообще до этого дошёл

Дело было на SceneX, и мне надо было быстро дать ассистенту доступ к провайдеру моделей, чтобы он мог их дёргать. И вот тут включается та самая логика спешки, которую, я уверен, ловил почти каждый, кто хоть раз что-то собирал с нейросетью под управлением. Когда тебе кажется, что вот сейчас один раз скинуть ключ прямо в сообщение это вообще ни о чём, ну подумаешь, мы же тут вдвоём, я и ассистент, кому какое дело. И я взял рабочий ключ и вставил его открытым текстом прямо в переписку. Не в файл, не в переменную окружения, а буквально в тело сообщения, как будто это адрес или название модели.

Реакция была мгновенной. Вместо того чтобы просто схватить ключ и побежать настраивать, ассистент затормозил и сказал: этот ключ надо отозвать и перевыпустить, его место только в `.env`, а `.env` должен быть в `.gitignore`, и в чат секреты не вставляют. То есть машина мне аккуратно объяснила то, что я и сам прекрасно знаю, но в моменте проигнорировал ради тридцати сэкономленных секунд.

Меня это, честно, в первую секунду взбесило, потому что я был в режиме «газуй, не тормози», и я ему ответил примерно так: «да иди нахуй с ключом, сам разюерусь». Вот прямо так, дословно, с опечаткой и всё. И знаете что? Он был прав, а я нет. Раздражение прошло за минуту, а ключ остался скомпрометированным до тех пор, пока я его реально не отозвал.

Почему «да там же только я» не работает

Тут хочется копнуть чуть глубже, а то получится «вставлять ключи плохо, не вставляйте», и всё, никакой пользы. Проблема не в том, что кто-то прямо сейчас сидит и читает вашу переписку, хотя и это исключать нельзя. Проблема в том, что секрет, попавший в чат, перестаёт быть под вашим контролем, и вы уже не можете честно сказать, где он осел. Переписка может попасть в логи, в историю, в какой-нибудь кэш, в скриншот, который вы потом кому-то покажете, в экспорт диалога. Вы видите аккуратное окно чата, а как оно устроено внутри и куда там утекает текст, нет.

А API-ключ от провайдера моделей это не игрушка, это прямой доступ к вашему балансу и к моделям за ваши деньги. Кто-то нашёл, кто-то жжёт ваши токены, и вы потом смотрите на счёт и не понимаете, откуда пришёл расход. Я уже писал про то, как два проекта встали разом, когда просто кончились деньги на API, так вот, представьте, что деньги кончились не потому, что вы их потратили, а потому что кто-то подобрал ваш засвеченный ключ. Совсем другой уровень обидно.

И вот что важно понять про работу с нейросетью именно в формате claude code api и любых агентов, которым вы даёте доступ к чему-то реальному. Чем мощнее инструмент, тем дороже ваша невнимательность. Раньше вы могли скинуть ключ другу в личку, и максимум, что бывало, друг забывал про него. Сейчас вы скидываете его в систему, которая ходит в интернет, дёргает внешние API и работает быстрее вас. Цена одного небрежного сообщения выросла, а привычка осталась прежней, и в этом весь капкан.

Где секретам реально место

Правильная схема скучная, и именно поэтому её все ленятся соблюдать. Секрет живёт в одном-единственном месте, в файле `.env`, который никогда не попадает в репозиторий, потому что он прописан в `.gitignore`. Код читает ключ из переменной окружения, а не из строки, которую вы вбили руками. В самом коде ключа нет, в коммитах ключа нет, в чате с ассистентом ключа нет, в скриншотах ключа нет.

У меня на этом проекте `.gitignore` исключает не только `.env`, но и вообще всё, что пахнет секретами или локальным состоянием: любые `*.env`, файлы с настройками и секретами, локальную базу. Логика простая, если в файле есть что-то, что я не хочу показывать чужому человеку, заглянувшему в репозиторий, этот файл не должен в репозиторий попадать никогда. Не «я аккуратно не закоммичу», а физически исключён, чтобы я не смог это сделать на автомате в три часа ночи.

И да, тут есть тонкий момент, который многих сбивает. Люди думают, что раз они работают с ии для автоматизации и вообще не пишут код руками, то и про секреты можно не думать, мол, нейросеть умная, сама разберётся. Не разберётся, если вы ей вручную скормили ключ в чат. Ассистент может настоять, может предупредить, мой как раз настоял, но он не может задним числом вынуть ключ из истории переписки и сделать так, будто его там не было. После того как вы нажали отправить, единственный реальный способ всё починить это перевыпустить ключ. Других нет.

Что делать прямо сейчас, если уже засветили

Раз уж это разбор реальной ошибки, давайте по делу. Если вы поняли, что секрет утёк, в чат, в публичный коммит, в скриншот, куда угодно, порядок такой. Сначала отзываете старый ключ в кабинете провайдера, чтобы он перестал работать, и только потом выпускаете новый, а не наоборот, чтобы не оставить рабочую дырку. Дальше кладёте новый ключ в `.env`, проверяете, что `.env` точно в `.gitignore` и не висит случайно в истории гита. И если ключ успел полежать на виду какое-то время, не поленитесь заглянуть в биллинг провайдера и посмотреть, не было ли странного расхода, потому что лучше узнать об этом самому, чем по нулевому балансу.

Звучит как занудство, но это ровно та занудная процедура, которая отделяет «потерял пять минут на перевыпуск» от «потерял баланс и пол-вечера на разбор полётов». Я выбираю первое, хоть в моменте меня от этого и подбешивало.

Что я из этого вынес

Самое неприятное в этой истории даже не сам косяк, а то, что я всё это знал заранее. Я не новичок, который впервые услышал слово `.env`, я прекрасно понимаю, как хранят секреты. И всё равно в режиме спешки рука сама вставила ключ в чат, потому что так было на полминуты быстрее. Вот и делайте выводы, знать правило и соблюдать его под давлением скорости это две очень разные вещи, и провал случается именно на стыке.

Поэтому теперь у меня правило простое и тупое, которое работает как раз потому, что тупое: секрет не покидает `.env` ни при каких обстоятельствах, как бы я ни торопился, и неважно, кто на том конце, живой человек или агент. Если очень хочется срезать угол на безопасности ради скорости, это первый признак, что надо притормозить ровно на одну минуту и сделать как положено. Минута сейчас всегда дешевле, чем разбор последствий потом, и это, пожалуй, единственная цифра, которую тут вообще стоит запоминать.