Библиотека · Запуск: оплата, секреты, законы, журналы

Безопасность в Claude Code — .env, secrets и защита данных

Уверенный пользователь55 минОбновлено: октябрь 2026
85 из 105 в библиотеке

Модуль: Профессиональная практика | Время: ~25 мин теории + 30 мин практики


Суть урока

Claude Code видит всё что в папке проекта — и может случайно показать это всему интернету через один неосторожный git push. Настроить security stack — это как поставить замок на дверь до того как въехать, а не после первого ограбления.


Ключевые концепции

  • .env — файл с секретами, живёт локально, никогда не попадает в Git
  • .gitignore — список того что Git не упаковывает в репозиторий
  • settings.json permissions — allow/deny списки для инструментов Claude; именно deny-правила закрывают файлы от Claude (файла .claudeignore в Claude Code нет)
  • Pre-commit hook — автоматическая проверка до коммита, останавливает утечку
  • Cloudflare / Vercel secrets — хранилище секретов для продакшна
  • 1Password CLI — мастер-хранилище, откуда всё берётся
  • Псевдонимизация PII — персональные данные клиентов никогда не идут в LLM сырыми

Теория

Почему это критично: Claude Code видит всё

🎨 Образ: Claude Code — это очень умный подрядчик которому ты дал ключи от всего офиса. Он может зайти в любую комнату, прочитать любой документ. Обычно это плюс. Но если ты случайно оставил ключи от сейфа на столе в общем доступе — проблема уже не в подрядчике.

Claude Code при работе читает файлы в текущей директории. Когда ты просишь "разберись с этим проектом" — он заглядывает во всё: исходники, конфиги, иногда .env. Если после этого делается git commit и git push — всё что Claude не исключил, идёт в репозиторий.

Реальная цена ошибки:

  • AWS ключ в публичном репо → боты находят за считанные минуты → счёт на тысячи долларов за ночь
  • Anthropic API ключ → кто-то потратит весь твой лимит за выходные → проект упал
  • Stripe production ключ → прямой доступ к деньгам клиентов
  • Database URL → полный дамп базы данных, включая данные клиентов

Правило которое нужно запомнить раз и навсегда: секрет, который хоть раз попал в Git-историю, считается публичным. Даже если ты сделал git rm в следующем коммите — в истории он навсегда. Единственное решение: сменить ключ.


Структура .env — правильно с первого раза

🎨 Образ: .env — это сейф в подсобке магазина. Витрина (код) для всех. Сейф (секреты) — только для кассира. Деньги на витрине не хранят.

Базовая структура .env файла:

bash
# .env — НИКОГДА не коммитить в Git

# === AI / LLM ===
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-proj-...
PERPLEXITY_API_KEY=pplx-...

# === Платежи ===
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...

# === База данных ===
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# === Telegram / Боты ===
TELEGRAM_BOT_TOKEN=7123456789:AAF...

# === Настройки окружения ===
NODE_ENV=development
LOG_LEVEL=info

Рядом с .env создаётся .env.example — шаблон без значений, который идёт в Git:

bash
# .env.example — COMMIT THIS FILE (значений нет, только ключи)

ANTHROPIC_API_KEY=sk-ant-your-key-here
OPENAI_API_KEY=sk-proj-your-key-here
STRIPE_SECRET_KEY=sk_live_your-key-here
DATABASE_URL=postgresql://user:password@host:5432/dbname
TELEGRAM_BOT_TOKEN=your-token-here
NODE_ENV=development

Это твоя документация для коллег (и для себя через полгода): какие переменные нужны, чтобы проект запустился.

Структура файлов в проекте:

Код
project/
├── .env              ← реальные ключи (НЕ в Git)
├── .env.example      ← шаблон без значений (в Git)
├── .env.test         ← mock-ключи для тестов (не в Git)
├── .gitignore        ← защита
├── .claude/
│   └── settings.json ← правила: что Claude не читает и не запускает
└── src/

.gitignore — первая линия защиты

🎨 Образ: .gitignore — список вещей которые не кладёшь в общий шкаф. Команда видит шкаф. Паспорт и ключи от сейфа — в своём кармане.

Создай до первого git init, а лучше до первого git add:

bash
# .gitignore

# Секреты — НИКОГДА не в Git
.env
.env.local
.env.*.local
.env.production
.env.staging

# Ключи и сертификаты
*.pem
*.key
*.p12
*.pfx
id_rsa
id_ed25519

# Зависимости
node_modules/
__pycache__/
*.pyc
.venv/

# Системные
.DS_Store
Thumbs.db

# IDE
.cursor/
.idea/
*.swp

Проверка перед каждым коммитом:

bash
git status
# .env не должен появляться в списке — если появился, стоп

Если .env уже попал в Git (это произошло):

bash
git rm --cached .env
git commit -m "Remove .env from tracking"
# Обязательно смени ВСЕ ключи из этого файла — они скомпрометированы

Как закрыть файлы от Claude: permissions.deny (а не .claudeignore)

Частая ошибка: многие статьи и ответы AI советуют создать файл .claudeignore. Такого файла в Claude Code нет, он ничего не делает и создаёт ложное чувство безопасности. Рабочий способ один: deny-правила в .claude/settings.json (см. следующий раздел). Git и Claude — разные инструменты, у каждого свои границы: .gitignore говорит Git что не трекать, deny говорит Claude что не читать.

json
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}

Что ещё помогает:

  • Не держи боевые секреты в папке проекта: в разработке нужен только dev-ключ, а production-ключи живут в хранилище платформы (раздел про production ниже).
  • Deny на Read закрывает встроенный инструмент чтения. Чтобы закрыть обходные пути через командную строку (cat .env), включай песочницу (/sandbox, доступна на поддерживаемых платформах) и добавляй deny на нужные команды.
  • Папки с данными клиентов (data/clients/, exports/, backups/) закрывай теми же правилами или вообще держи вне проекта.

🎨 Образ: Если .gitignore — это список что не отправлять коллегам, то deny-правила — это список что не показывать временному консультанту. Консультанту не нужно видеть договоры с клиентами чтобы настроить бухгалтерию. И помни: табличка «не входить» на двери без замка (.claudeignore) не защищает.


settings.json permissions — allow/deny списки

Хак #30 из урока 32 хака Claude Code: settings.json позволяет жёстко зафиксировать что Claude может и не может делать — независимо от того что ты напишешь в чате.

Файл: .claude/settings.json

json
{
  "permissions": {
    "allow": [
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git status)",
      "Bash(git log *)",
      "Bash(npm install)",
      "Bash(npm run *)",
      "Bash(node *)",
      "Bash(python *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Bash(git push -f *)",
      "Bash(DROP *)",
      "Bash(DELETE FROM *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(**/*.pem)",
      "Read(**/*.key)",
      "Read(./secrets/**)"
    ]
  }
}

Что это даёт:

  • deny: ["Read(./.env)"] — Claude не читает .env даже если ты попросишь
  • deny: ["Bash(rm -rf *)"] — защита от случайного удаления всего
  • deny: ["Bash(git push --force *)"] — force push только вручную, не через Claude
  • allow список — явный список того что разрешено, остальное требует подтверждения (в режиме auto, который с версии 2.1.283 стартует по умолчанию, действия дополнительно проверяет отдельная модель-классификатор, но deny-правила остаются главным барьером)

🎨 Образ: это как список допусков на объекте. Охранник пускает только по спискам — даже если человек говорит "директор разрешил". Список важнее слов.

Важно: settings.json коммитится в репозиторий (без секретов — только правила). Так настройки едут с проектом.


Pre-commit hook — автоматическая проверка

🎨 Образ: Pre-commit hook — как рамка металлодетектора на выходе из режимного объекта. Нельзя выйти не пройдя проверку. Забыл ключ в кармане — рамка сработала до того как ты вышел на улицу.

Создаётся в .git/hooks/pre-commit:

bash
#!/bin/bash
# Pre-commit security check
# Устанавливается: chmod +x .git/hooks/pre-commit

echo "Проверка секретов перед коммитом..."

# Паттерны которые не должны попасть в коммит
PATTERNS=(
  "sk-ant-"
  "sk-proj-"
  "sk_live_"
  "sk_test_"
  "AKIA[0-9A-Z]{16}"
  "whsec_"
  "xoxb-"
  "xoxp-"
  "ghp_"
  "glpat-"
  "password\s*=\s*['\"][^'\"]{8,}"
  "secret\s*=\s*['\"][^'\"]{8,}"
  "DATABASE_URL\s*=\s*postgresql"
)

FOUND=0
for PATTERN in "${PATTERNS[@]}"; do
  if git diff --cached | grep -iE "$PATTERN" > /dev/null 2>&1; then
    echo ""
    echo "СТОП: обнаружен секрет в коммите!"
    echo "Паттерн: $PATTERN"
    echo ""
    git diff --cached | grep -iE --color "$PATTERN"
    FOUND=1
  fi
done

if [ $FOUND -eq 1 ]; then
  echo ""
  echo "Коммит заблокирован. Убери секреты из staged файлов."
  echo "Используй: git reset HEAD <файл> чтобы убрать файл из staging"
  exit 1
fi

echo "Секретов не найдено. Коммит разрешён."
exit 0

Установка:

bash
chmod +x .git/hooks/pre-commit

Или через pre-commit (более мощный вариант):

bash
pip install pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.x.x  # актуальный тег смотри в репозитории gitleaks
    hooks:
      - id: gitleaks
bash
pre-commit install
# Теперь автоматически при каждом git commit

Проверка что хук работает:

bash
# Временно добавь строку с "секретом" в файл
echo "ANTHROPIC_API_KEY=sk-ant-test123" >> test.txt
git add test.txt
git commit -m "test"
# Должно сработать блокирование
git reset HEAD test.txt
rm test.txt

Production secrets: Cloudflare, Vercel, Railway

В продакшне .env файл не существует. Секреты хранятся в зашифрованных хранилищах платформы.

Cloudflare Workers Secrets:

bash
# Установка секрета (wrangler спросит значение интерактивно)
wrangler secret put ANTHROPIC_API_KEY
> Enter a secret value: [вводишь ключ — не видно на экране]

# Список установленных секретов (только имена, значения недоступны)
wrangler secret list

# Удаление
wrangler secret delete OLD_KEY

В коде Cloudflare Worker секреты доступны через объект env:

javascript
export default {
  async fetch(request, env) {
    // env.ANTHROPIC_API_KEY — пришло из wrangler secret
    const client = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY });
  }
};

Vercel Environment Variables:

bash
# Через CLI
vercel env add ANTHROPIC_API_KEY production
vercel env add ANTHROPIC_API_KEY preview
vercel env add ANTHROPIC_API_KEY development

# Или через dashboard: vercel.com → Project → Settings → Environment Variables

Railway:

bash
# Через CLI (синтаксис команды смотри в документации Railway, он менялся)
railway variables set ANTHROPIC_API_KEY=sk-ant-...

# Или через dashboard: railway.app → Project → Variables

Принцип: разные окружения — разные ключи. Dev ключ с небольшим лимитом расходов. Production ключ с рабочим лимитом. Баг в разработке не должен тратить production-бюджет.


1Password CLI — мастер-хранилище

🎨 Образ: 1Password — это банковский сейф где хранится оригинал. .env — рабочая копия у тебя в кармане. Cloudflare secrets — копия в офисе. Оригинал один — в сейфе.

Структура vault в 1Password:

Код
1Password → AI Projects (отдельный vault)
├── Newsletter Automation
│   ├── Anthropic API Key (prod)
│   ├── Anthropic API Key (dev)  ← отдельный с лимитом
│   └── Stripe Keys
├── Telegram Bot Project
│   └── Bot Token
└── Shared Infrastructure
    ├── Cloudflare API Token
    └── GitHub Token

1Password CLI — автоматическое заполнение .env:

bash
# Установка
brew install 1password-cli
op signin

# В .env.example укажи ссылки на 1Password
ANTHROPIC_API_KEY=op://AI-Projects/Newsletter/anthropic-prod-key
STRIPE_SECRET_KEY=op://AI-Projects/Newsletter/stripe-secret

# Автоматически заполняет .env из хранилища
op inject -i .env.example -o .env

Больше не копируешь ключи вручную — только op inject и готово.


Security review командой Claude

Самый быстрый способ найти проблемы в существующем проекте — попросить Claude сделать аудит:

Напиши в чат
Сделай security review этого проекта:

1. Нет ли API ключей или паролей захардкоженных в коде (не в .env)?
2. Все ли sensitive файлы в .gitignore?
3. Есть ли .env.example без реальных значений?
4. Нет ли PII данных клиентов в логах или hardcoded строках?
5. Правильно ли настроены permissions в .claude/settings.json?

Покажи список найденных проблем с указанием файла и строки.

Результат — конкретный список: src/api.js:23 — STRIPE_KEY захардкожен. Фиксируешь по очереди. Для изменений в ветке есть и встроенная команда /security-review: она разбирает отличия вашей ветки от основной на типичные уязвимости. Это помощник, а не замена проверки человеком.


PII и данные клиентов — псевдонимизация

🎨 Образ: Врач на конференции рассказывает о клиническом случае — но никогда не называет имя пациента. "Мужчина 45 лет" вместо "Иван Петров". Тот же принцип с данными клиентов в LLM.

PII (Personally Identifiable Information) — имена, телефоны, email, паспорта, ИНН, адреса — не должны идти в Claude сырыми.

До — как делать нельзя:

python
# Передаём реальные данные в Claude — нарушение
prompt = f"""
Проанализируй клиента:
Имя: Иван Петров
Телефон: +7 999 123-45-67
Email: [email protected]
Бюджет: $80,000
"""

После — правильно:

python
# Псевдонимизация перед отправкой в LLM
def pseudonymize(client):
    return {
        "id": f"Client_{client['id']}",
        "budget_usd": client['budget'],
        "region": client['city'],          # только регион, не точный адрес
        "property_type": client['type']
    }

client_data = pseudonymize(raw_client)
prompt = f"""
Проанализируй клиента:
ID: {client_data['id']}
Бюджет: ${client_data['budget_usd']:,}
Регион: {client_data['region']}
Тип недвижимости: {client_data['property_type']}
"""

Правила для PII:

  • Имена → Client_42, User_789
  • Телефоны → не передавать, если не нужны для задачи
  • Email → не передавать, если не нужны
  • Бюджет → можно передавать в диапазонах ($50K-100K) если точная цифра не нужна
  • Адреса → только город/регион, не точный адрес

Это не паранойя — это GDPR в Европе, Ley Orgánica в Испании, здравый смысл везде. Подробнее о регулировании: AI Regulation & Compliance 2026.


Практика

Задание: настроить базовый security stack

Шаг 1: Базовая защита

bash
mkdir secure-project && cd secure-project
git init

# Создай .gitignore
cat > .gitignore << 'EOF'
.env
.env.*
*.pem
*.key
node_modules/
__pycache__/
.DS_Store
EOF

# Создай .env с тестовыми данными
cat > .env << 'EOF'
ANTHROPIC_API_KEY=sk-ant-test-placeholder
STRIPE_SECRET_KEY=sk_live_test-placeholder
DATABASE_URL=postgresql://localhost:5432/testdb
EOF

# Создай .env.example (идёт в Git)
cat > .env.example << 'EOF'
ANTHROPIC_API_KEY=sk-ant-your-key-here
STRIPE_SECRET_KEY=sk_live_your-key-here
DATABASE_URL=postgresql://user:password@host:5432/dbname
EOF

# Проверка — .env не должен быть в git status
git status
# Вывод: только .gitignore и .env.example — НЕ .env

Шаг 2: Вынеси лишнее из папки проекта

Проверь, что в папке проекта лежит только dev-ключ. Боевые ключи оставь в хранилище платформы и менеджере паролей. Файла .claudeignore создавать не нужно: он не работает, закрывать файлы будем правилами в следующем шаге.

Шаг 3: settings.json — закрыть файлы и опасные команды

bash
mkdir -p .claude

cat > .claude/settings.json << 'EOF'
{
  "permissions": {
    "allow": [
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git status)",
      "Bash(git log *)",
      "Bash(npm install)",
      "Bash(npm run *)",
      "Bash(node *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}
EOF

Шаг 4: Pre-commit hook

bash
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
echo "Security check..."

PATTERNS=("sk-ant-" "sk-proj-" "sk_live_" "whsec_" "AKIA" "ghp_")
FOUND=0

for P in "${PATTERNS[@]}"; do
  if git diff --cached | grep -E "$P" > /dev/null 2>&1; then
    echo "СТОП: найден секрет (паттерн: $P)"
    FOUND=1
  fi
done

[ $FOUND -eq 1 ] && exit 1
echo "OK — секретов не найдено"
exit 0
EOF

chmod +x .git/hooks/pre-commit

Протестируй что хук работает:

bash
echo "ANTHROPIC_API_KEY=sk-ant-realkey123" >> test-leak.txt
git add test-leak.txt
git commit -m "test"
# Должно заблокировать
git reset HEAD test-leak.txt && rm test-leak.txt

Шаг 5: Security audit через Claude

Открой Claude Code в папке проекта и напиши:

Напиши в чат
Сделай security audit этого проекта:
1. Нет ли захардкоженных секретов в .js/.py файлах?
2. Правильно ли настроен .gitignore?
3. Закрыты ли чувствительные файлы правилами deny в .claude/settings.json?
4. Проверь .claude/settings.json — достаточно ли ограничений?
Дай список конкретных проблем с файлами и строками.

Шаг 6: Первый безопасный коммит

bash
git add .gitignore .env.example .claude/settings.json
git commit -m "Security stack: gitignore, settings.json deny rules, pre-commit hook"

# Проверь что .env не попал
git show HEAD --name-only | grep .env
# Вывод должен быть пустым

Результат: три слоя защиты — .gitignore + pre-commit hook + settings.json deny — заметно снижают риск случайной утечки секрета в Git. Полной гарантии они не дают: ключи всё равно нужно хранить правильно и менять при малейшем подозрении.


Инструменты и ресурсы

  • gitleaks — сканер утечек секретов в Git-репозиториях, brew install gitleaks
  • git-secrets — pre-commit хук от AWS, brew install git-secrets
  • pre-commit — фреймворк для pre-commit хуков, pip install pre-commit
  • 1Password CLI — op inject для автозаполнения .env
  • Cloudflare Workers Secrets — wrangler secret put
  • Vercel Environment Variables — через dashboard или vercel env add
  • dotenv (Node.js) — npm install dotenv
  • python-dotenv (Python) — pip install python-dotenv
  • GitHub Secret Scanning — включено по умолчанию, уведомит если ключ попал в публичный репо
  • Claude Code docs: Permissions — официальная документация по правилам доступа

Ключевые выводы

Секрет, попавший в Git-историю, считается публичным навсегда — даже если репозиторий приватный. Единственное решение: сменить ключ.

Три слоя защиты: .gitignore (не трекает), pre-commit hook (блокирует коммит), settings.json deny (Claude не читает). Вместе они сильно снижают риск утечки.

Файла .claudeignore в Claude Code не существует. .gitignore говорит Git что не трекать, а deny-правила в settings.json говорят Claude что не читать.

PII данные клиентов псевдонимизируются до отправки в LLM. Client_42 вместо "Иван Петров".

Dev и prod — всегда разные ключи. Баг в разработке не должен стоить производственного бюджета.


Следующий урок

→ AI Ethics & Safety — галлюцинации, атаки, предвзятость: как не доверять AI слепо

Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс