Суть урока
Claude Code видит всё что в папке проекта — и может случайно показать это всему интернету через один неосторожный git push. Настроить security stack — это как поставить замок на дверь до того как въехать, а не после первого ограбления.
Ключевые концепции
.env— файл с секретами, живёт локально, никогда не попадает в Git.gitignore— список того что Git не упаковывает в репозиторийsettings.jsonpermissions — allow/deny списки для инструментов Claude; именно deny-правила закрывают файлы от Claude (файла.claudeignoreв Claude Code нет)- Pre-commit hook — автоматическая проверка до коммита, останавливает утечку
- Cloudflare / Vercel secrets — хранилище секретов для продакшна
- 1Password CLI — мастер-хранилище, откуда всё берётся
- Псевдонимизация PII — персональные данные клиентов никогда не идут в LLM сырыми
Теория
Почему это критично: Claude Code видит всё
Claude Code при работе читает файлы в текущей директории. Когда ты просишь "разберись с этим проектом" — он заглядывает во всё: исходники, конфиги, иногда .env. Если после этого делается git commit и git push — всё что Claude не исключил, идёт в репозиторий.
Реальная цена ошибки:
- AWS ключ в публичном репо → боты находят за считанные минуты → счёт на тысячи долларов за ночь
- Anthropic API ключ → кто-то потратит весь твой лимит за выходные → проект упал
- Stripe production ключ → прямой доступ к деньгам клиентов
- Database URL → полный дамп базы данных, включая данные клиентов
Правило которое нужно запомнить раз и навсегда: секрет, который хоть раз попал в Git-историю, считается публичным. Даже если ты сделал git rm в следующем коммите — в истории он навсегда. Единственное решение: сменить ключ.
Структура .env — правильно с первого раза
Базовая структура .env файла:
# .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:
# .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 — первая линия защиты
Создай до первого git init, а лучше до первого git add:
# .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Проверка перед каждым коммитом:
git status
# .env не должен появляться в списке — если появился, стопЕсли .env уже попал в Git (это произошло):
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 что не читать.
{
"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/) закрывай теми же правилами или вообще держи вне проекта.
settings.json permissions — allow/deny списки
Хак #30 из урока 32 хака Claude Code: settings.json позволяет жёстко зафиксировать что Claude может и не может делать — независимо от того что ты напишешь в чате.
Файл: .claude/settings.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 только вручную, не через Claudeallowсписок — явный список того что разрешено, остальное требует подтверждения (в режиме auto, который с версии 2.1.283 стартует по умолчанию, действия дополнительно проверяет отдельная модель-классификатор, но deny-правила остаются главным барьером)
Важно: settings.json коммитится в репозиторий (без секретов — только правила). Так настройки едут с проектом.
Pre-commit hook — автоматическая проверка
Создаётся в .git/hooks/pre-commit:
#!/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Установка:
chmod +x .git/hooks/pre-commitИли через pre-commit (более мощный вариант):
pip install pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.x.x # актуальный тег смотри в репозитории gitleaks
hooks:
- id: gitleakspre-commit install
# Теперь автоматически при каждом git commitПроверка что хук работает:
# Временно добавь строку с "секретом" в файл
echo "ANTHROPIC_API_KEY=sk-ant-test123" >> test.txt
git add test.txt
git commit -m "test"
# Должно сработать блокирование
git reset HEAD test.txt
rm test.txtProduction secrets: Cloudflare, Vercel, Railway
В продакшне .env файл не существует. Секреты хранятся в зашифрованных хранилищах платформы.
Cloudflare Workers Secrets:
# Установка секрета (wrangler спросит значение интерактивно)
wrangler secret put ANTHROPIC_API_KEY
> Enter a secret value: [вводишь ключ — не видно на экране]
# Список установленных секретов (только имена, значения недоступны)
wrangler secret list
# Удаление
wrangler secret delete OLD_KEYВ коде Cloudflare Worker секреты доступны через объект env:
export default {
async fetch(request, env) {
// env.ANTHROPIC_API_KEY — пришло из wrangler secret
const client = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY });
}
};Vercel Environment Variables:
# Через 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 VariablesRailway:
# Через CLI (синтаксис команды смотри в документации Railway, он менялся)
railway variables set ANTHROPIC_API_KEY=sk-ant-...
# Или через dashboard: railway.app → Project → VariablesПринцип: разные окружения — разные ключи. Dev ключ с небольшим лимитом расходов. Production ключ с рабочим лимитом. Баг в разработке не должен тратить production-бюджет.
1Password CLI — мастер-хранилище
Структура 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 Token1Password CLI — автоматическое заполнение .env:
# Установка
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 и данные клиентов — псевдонимизация
PII (Personally Identifiable Information) — имена, телефоны, email, паспорта, ИНН, адреса — не должны идти в Claude сырыми.
До — как делать нельзя:
# Передаём реальные данные в Claude — нарушение
prompt = f"""
Проанализируй клиента:
Имя: Иван Петров
Телефон: +7 999 123-45-67
Email: ivan@mail.ru
Бюджет: $80,000
"""После — правильно:
# Псевдонимизация перед отправкой в 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: Базовая защита
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 — закрыть файлы и опасные команды
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
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Протестируй что хук работает:
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: Первый безопасный коммит
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 слепо
Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс