Grey Haven's security best practices - input validation, output sanitization, multi-tenant RLS, secret management with Doppler, rate limiting, OWASP Top 10 for TanStack/FastAPI stack. Use when implementing security-critical features.
View on GitHubgreyhaven-ai/claude-code-config
security
grey-haven-plugins/security/skills/security-practices/SKILL.md
January 21, 2026
Select agents to install to:
npx add-skill https://github.com/greyhaven-ai/claude-code-config/blob/main/grey-haven-plugins/security/skills/security-practices/SKILL.md -a claude-code --skill grey-haven-security-practicesInstallation paths:
.claude/skills/grey-haven-security-practices/# Grey Haven Security Practices
Follow Grey Haven Studio's security best practices for TanStack Start and FastAPI applications.
## Secret Management with Doppler
**CRITICAL**: NEVER commit secrets to git. Always use Doppler.
### Doppler Setup
```bash
# Install Doppler CLI
brew install dopplerhq/cli/doppler
# Authenticate
doppler login
# Setup project
cd /path/to/project
doppler setup
# Access secrets
doppler run -- npm run dev # TypeScript
doppler run -- python app/main.py # Python
```
### Required Secrets (Doppler)
```bash
# Auth
BETTER_AUTH_SECRET=<random-32-bytes>
JWT_SECRET_KEY=<random-32-bytes>
# Database
DATABASE_URL_ADMIN=postgresql://...
DATABASE_URL_AUTHENTICATED=postgresql://...
# APIs
RESEND_API_KEY=re_...
STRIPE_SECRET_KEY=sk_...
OPENAI_API_KEY=sk-...
# OAuth
GOOGLE_CLIENT_SECRET=GOCSPX-...
GITHUB_CLIENT_SECRET=...
```
### Accessing Secrets in Code
```typescript
// [OK] Correct - Use process.env (Doppler provides at runtime)
const apiKey = process.env.OPENAI_API_KEY!;
// [X] Wrong - Hardcoded secrets
const apiKey = "sk-..."; // NEVER DO THIS!
```
```python
# [OK] Correct - Use os.getenv (Doppler provides at runtime)
import os
api_key = os.getenv("OPENAI_API_KEY")
# [X] Wrong - Hardcoded secrets
api_key = "sk-..." # NEVER DO THIS!
```
## Input Validation
### TypeScript (Zod Validation)
```typescript
import { z } from "zod";
// [OK] Validate all user input
const UserCreateSchema = z.object({
email_address: z.string().email().max(255),
name: z.string().min(1).max(100),
age: z.number().int().min(0).max(150),
});
export const createUser = createServerFn("POST", async (data: unknown) => {
// Validate input
const validated = UserCreateSchema.parse(data);
// Now safe to use
await db.insert(users).values(validated);
});
```
### Python (Pydantic Validation)
```python
from pydantic import BaseModel, EmailStr, Field, validator
class UserCreate(BaseModel):
"""User creation schema with validation."""
email_Issues Found: