Чек-лист безопасности
Ваша карточка будет работать на чужих машинах рядом с агентами, которые могут править код и запускать команды. Приложение многое делает, чтобы её сдержать, — но что вы попросите и что сделаете с этим, зависит от вас. Эта страница — чек-лист, который стоит пройти перед тем, как делиться карточкой, и снова перед каждым релизом.
Что приложение уже гарантирует
Ослабить это вы не должны (и не сможете):
- Карточка работает в отдельном изолированном процессе без доступа к приложению, Node.js, другим
карточкам, cookies и
localStorageи не может открывать окна, уводить приложение на другую страницу или рисовать за пределами своей коробки. - Она ни до чего не может дотянуться — ни до сети, ни до файлов, ни до агентов, — кроме как через SDK, а приложение сверяет каждый запрос с тем, что выдал пользователь.
- Её страница загружает только файлы из собственного пакета: никаких удалённых скриптов, встроенных
скриптов и
eval. - В страницах карточек отключены WebRTC и предварительный DNS, так что обходных каналов в сеть нет. Формы никогда не уводят страницу, вложенные фреймы удаляются, а писать в буфер обмена сама страница не может.
- Решения и секреты запрашиваются в собственном диалоге приложения на всё окно, который карточка не может подделать; ваш текст появляется там только как цитата.
- Даже с
fs.writeнельзя изменить.git, настройки агентов и редакторов, CI-процессы и настройки пакетных менеджеров, а если воркспейс — домашняя папка или корень диска, доступа к файлам у карточек нет вовсе. - Промпты и команды ограничены на карточку (6 и 30 в минуту), каким бы способом их ни отправляли, а промпты в очереди выбрасываются, когда пропадает стрелка или разрешение.
- Данные доходят до другой карточки или агента только по стрелке, которую провёл пользователь.
- Секреты, введённые в настройки
secret, никогда не доходят до карточки. - У каждой копии карточки своё хранилище; пакеты не могут читать данные друг друга.
Перед публикацией
Разрешения
- Каждое разрешение действительно используется. Уберите лишние — каждое из них это строка в диалоге установки и повод отказаться.
- У каждого разрешения есть
reasonпростыми словами. - Редко нужные сильные разрешения сделаны
optionalи запрашиваются в момент использования. - В
networkперечислены конкретные хосты. Никаких доменов «на всё», сервисов для вставки текста, сокращателей ссылок и масок*., без которых можно обойтись. - Вы не используете
network.local, если карточка не про локальные серверы.
Промпты, инструменты и команды — самая рискованная часть
- Ничего из интернета, файла, порта или вывода агента не уходит в
agents.promptилиterminals.run/write, пока пользователь это не увидит. Иначе одна враждебная веб-страница или файл может перехватить управление агентом пользователя (внедрение промптов). - Промпты, собранные из недоверенного текста, отправляются с
submit: false, чтобы пользователь сам проверил и отправил их. - Команды — это фиксированные строки или собираются из настроек, которые ввёл пользователь, но никогда не из скачанных данных. Всё, что подставляете, экранируйте.
- Инструменты, которые может вызвать агент, не делают ничего разрушительного (запись файлов,
команды, промпты, трата денег) без предварительного
card.ui.confirm. - Результаты инструментов со сторонним содержимым говорят, откуда оно, и остаются короткими.
- Вы никогда не отправляете промпты в цикле. Лимит — 6 промптов в минуту, и бюджет всё равно считается.
Секреты
- API-ключи — это настройки
secret, которые используются как{{secret:key}}в заголовках, — никогда не текстовое поле внутри карточки, не хранилище, не код и не репозиторий. - Карточка не просит пароли или ключи внутри своего тела. Пользователям сказано, что NeuroSquad так никогда не делает и что настоящий запрос затемняет всё окно.
- Карточке не нужны секреты на
localhost— туда они никогда не отправляются.
Файлы
-
fs.writeдействительно нужен. Если вы только выпускаете отчёт, подумайте о том, чтобы отправлять его в заметку. - Вы пишете только туда, где этого ждёт пользователь (например, в папку из настройки), и никогда не поверх конфигурации, lock-файлов, файлов CI или скриптов, которые выполняются при сборке.
- Вы используете
ifMtimeMs, когда переписываете файл, который пользователь может править. - Вы не читаете
.envи другие файлы с секретами, если в этом не заявленное назначение карточки.
Что вы показываете и отправляете
- Сторонний текст выводится как текст (
textContent), а не как HTML (innerHTML). Худшее песочница остановит, но вашу карточку всё равно можно испортить или запутать. - Порты отправляют только то, что сказано в их описании.
- Вы не реагируете на события
messageуwindow: написать в ваш фрейм может любая карточка. Доверять можно только каналу SDK.
Упаковка и обновления
-
pack --dry-runперечисляет только то, что вы собирались выпустить, — никаких.env, ключей, личных заметок,node_modulesили тестовых данных с настоящими сведениями. (packотказывается упаковывать файлы, похожие на учётные данные, если не передать--allow-secret-files.) - Ваше имя и автор не выдают себя за NeuroSquad, official или verified.
- На аккаунте GitHub включена двухфакторная аутентификация. Любой, кто может пушить в ваш репозиторий, может выпустить обновление вашим пользователям.
- Зависимости зафиксированы (lock-файл), и перед релизом вы собираете с чистой установки.
- Изменения, добавляющие разрешения, выходят отдельным релизом с объяснением.
Поведение
- Карточка ставит на паузу опрос и анимации, когда её не видно, и сохраняется в
onSuspend. - Сетевой опрос разумный (лимит — 120 запросов в минуту; держитесь намного ниже).
- Карточка работает — упрощается, объясняет, — когда разрешение отозвано.
Нашли, как карточке выбраться из своей коробки, получить то, что ей не выдавали, или обмануть собственные диалоги приложения? Это уязвимость NeuroSquad, а не вашей карточки, — сообщите команде лично, через сервер в Discord, а не в открытой ветке.
Что говорят пользователям
Диалог установки говорит пользователям этими словами, что карточка — код сообщества, который NeuroSquad не проверял, что каждое разрешение означает в худшем случае (например, что при доступе к сети «туда может уйти всё, что видит карточка») и что «всё внутри карточки принадлежит самой карточке». Пишите описание и причины так, чтобы осторожный пользователь, прочитав эти строки, всё равно согласился.