/security
OWASP security patterns, secrets management, security testing
Claude Code
$ npx -y skills add alinaqi/maggy --skill security --agent claude-code
Codex
$ npx skills add alinaqi/maggy --skill security -a codex -y
Cursor
$ npx skills add alinaqi/maggy --skill security -a cursor -y
Gemini CLI
$ npx skills add alinaqi/maggy --skill security -a gemini-cli -y
GitHub Copilot
$ npx skills add alinaqi/maggy --skill security -a github-copilot -y
OpenCode
$ npx skills add alinaqi/maggy --skill security -a opencode -y
Windsurf
$ npx skills add alinaqi/maggy --skill security -a windsurf -y
SKILL.md
security.SKILL.mdname: security
description: OWASP security patterns, secrets management, security testing
when-to-use: When writing code that handles auth, user input, API keys, or when security review is requested
user-invocable: true
allowed-tools: [Read, Glob, Grep, Bash]
effort: high
Security Skill
Security best practices and automated security testing for all projects.
> This skill is **preventive** — how to write and ship secure code. To *audit* > an existing codebase or PR for vulnerabilities, use the `security-audit` skill > (structured, adversarial, evidence-grounded); for a quick pass over the current > branch, run `/security-review`.
---
Core Principle
**Security is not optional.** Every project must pass security checks before merge. Assume all input is malicious, all secrets will leak if committed, and all dependencies have vulnerabilities.
---
Required Security Setup
1. Gitignore (Non-Negotiable)
Every project must have these in `.gitignore`:
# Environment files - NEVER commit
.env
.env.*
!.env.example
# Secrets
*.pem
*.key
*.p12
*.pfx
credentials.json
secrets.json
*-credentials.json
service-account*.json
# IDE and OS
.idea/
.vscode/settings.json
.DS_Store
Thumbs.db
# Dependencies
node_modules/
__pycache__/
*.pyc
.venv/
venv/
# Build outputs
dist/
build/
*.egg-info/
# Logs that might contain sensitive data
*.log
logs/
2. Environment Variables
**Create `.env.example`** with all required vars (no values):
# .env.example - Copy to .env and fill in values
# Server-side only (NEVER prefix with VITE_ or NEXT_PUBLIC_)
DATABASE_URL=
ANTHROPIC_API_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# Client-side safe (public, non-sensitive)
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=
Frontend Environment Variables (Critical!)
**NEVER put secrets in client-exposed env vars:**
| Framework | Client-Exposed Prefix | Server-Only | |-----------|----------------------|-------------| | Vite | `VITE_*` | No prefix | | Next.js | `NEXT_PUBLIC_*` | No prefix | | Create React App | `REACT_APP_*` | N/A (no server) |
// WRONG - Secret exposed to browser bundle!
const apiKey = import.meta.env.VITE_ANTHROPIC_API_KEY;
// CORRECT - Only public values client-side
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
// CORRECT - Secrets stay server-side only
// In API route or server function:
const apiKey = process.env.ANTHROPIC_API_KEY;
**Vercel Environment Variables:**
- In Vercel dashboard, secrets without `VITE_` prefix are server-only
- Only `VITE_*` vars are bundled into client code
- Always verify in browser devtools → Sources → your bundle that secrets aren't exposed
**Validate environment at startup:**
// config/env.ts
import { z } from 'zod';
const envSchema = z.object({
DATABASE_URL: z.string().url(),
ANTHROPIC_API_KEY: z.string().min(1),
NODE_ENV: z.enum(['development', 'production', 'test']),
});
export const env = envSchema.parse(process.env);# config/env.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
anthropic_api_key: str
environment: str = "development"
class Config:
env_file = ".env"
settings = Settings()---
Security Tests
Pre-Commit Security Checks
Add to pre-commit hooks:
**For all projects:**
# .pre-commit-config.yaml (add to existing)
repos:
# Detect secrets
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
# Check for security issues in dependencies
- repo: local
hooks:
- id: security-check
name: security-check
entry: ./scripts/security-check.sh
language: script
pass_filenames: false**TypeScript/JavaScript:**
// package.json scripts
{
"scripts": {
"security:audit": "npm audit --audit-level=high",
"security:secrets": "npx secretlint '**/*'",
"security:deps": "npx better-npm-audit audit"
}
}**Python:**
# Add to dev dependencies
pip install safety bandit
# Commands
safety check # Check dependencies for vulnerabilities
bandit -r src/ # Static security analysis
Security Check Script
Create `scripts/security-check.sh`:
#!/bin/bash
set -e
echo "Running security checks..."
# Check for secrets in staged files
echo "Checking for secrets..."
if command -v detect-secrets &> /dev/null; then
detect-secrets scan --baseline .secrets.baseline
fi
# Check .env is not staged
if git diff --cached --name-only | grep -E '^\.env$|^\.env\.' | grep -v '\.example$'; then
echo "ERROR: .env file is staged for commit!"
exit 1
fi
# Check for common secret patterns in staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if echo "$STAGED_FILES" | xargs grep -l -E '(password|secret|api_key|apikey|token|private_key)\s*[:=]\s*["\047][^"\047]+["\047]' 2>/dev/null; then
echo "ERROR: Possible secrets found in staged files!"
exit 1
fi
# Language-specific checks
if [ -f "package.json" ]; then
echo "Checking npm dependencies..."
npm audit --audit-level=high || echo "Warning: npm audit found issues"
fi
if [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then
echo "Checking Python dependencies..."
if command -v safety &> /dev/null; then
safety check || echo "Warning: safety found issues"
fi
fi
echo "Security checks passed!"chmod +x scripts/security-check.sh
---
GitHub Actions Security Workflow
Create `.github/workflows/security.yml`:
name: Security
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run weekly on Monday at 9am UTC
- cron: '0 9 * * 1'
jobs:
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect secrets
uses: trufflesecurity/trufflehog@mainRead more
name: security description: OWASP security patterns, secrets management, security testing when-to-use: When writing code that handles auth, user input, API keys, or when security review is requested user-invocable: true allowed-tools: [Read, Glob, Grep, Bash] effort: high
Security Skill
Security best practices and automated security testing for all projects.
> This skill is **preventive** — how to write and ship secure code. To *audit* > an existing codebase or PR for vulnerabilities, use the `security-audit` skill > (structured, adversarial, evidence-grounded); for a quick pass over the current > branch, run `/security-review`.
---
Core Principle
**Security is not optional.** Every project must pass security checks before merge. Assume all input is malicious, all secrets will leak if committed, and all dependencies have vulnerabilities.
---
Required Security Setup
1. Gitignore (Non-Negotiable)
Every project must have these in `.gitignore`:
# Environment files - NEVER commit .env .env.* !.env.example # Secrets *.pem *.key *.p12 *.pfx credentials.json secrets.json *-credentials.json service-account*.json # IDE and OS .idea/ .vscode/settings.json .DS_Store Thumbs.db # Dependencies node_modules/ __pycache__/ *.pyc .venv/ venv/ # Build outputs dist/ build/ *.egg-info/ # Logs that might contain sensitive data *.log logs/
2. Environment Variables
**Create `.env.example`** with all required vars (no values):
# .env.example - Copy to .env and fill in values # Server-side only (NEVER prefix with VITE_ or NEXT_PUBLIC_) DATABASE_URL= ANTHROPIC_API_KEY= SUPABASE_SERVICE_ROLE_KEY= # Client-side safe (public, non-sensitive) VITE_SUPABASE_URL= VITE_SUPABASE_ANON_KEY=
Frontend Environment Variables (Critical!)
**NEVER put secrets in client-exposed env vars:**
| Framework | Client-Exposed Prefix | Server-Only | |-----------|----------------------|-------------| | Vite | `VITE_*` | No prefix | | Next.js | `NEXT_PUBLIC_*` | No prefix | | Create React App | `REACT_APP_*` | N/A (no server) |
// WRONG - Secret exposed to browser bundle! const apiKey = import.meta.env.VITE_ANTHROPIC_API_KEY; // CORRECT - Only public values client-side const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; // CORRECT - Secrets stay server-side only // In API route or server function: const apiKey = process.env.ANTHROPIC_API_KEY;
**Vercel Environment Variables:**
- In Vercel dashboard, secrets without `VITE_` prefix are server-only
- Only `VITE_*` vars are bundled into client code
- Always verify in browser devtools → Sources → your bundle that secrets aren't exposed
**Validate environment at startup:**
// config/env.ts
import { z } from 'zod';
const envSchema = z.object({
DATABASE_URL: z.string().url(),
ANTHROPIC_API_KEY: z.string().min(1),
NODE_ENV: z.enum(['development', 'production', 'test']),
});
export const env = envSchema.parse(process.env);# config/env.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
anthropic_api_key: str
environment: str = "development"
class Config:
env_file = ".env"
settings = Settings()---
Security Tests
Pre-Commit Security Checks
Add to pre-commit hooks:
**For all projects:**
# .pre-commit-config.yaml (add to existing)
repos:
# Detect secrets
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
# Check for security issues in dependencies
- repo: local
hooks:
- id: security-check
name: security-check
entry: ./scripts/security-check.sh
language: script
pass_filenames: false**TypeScript/JavaScript:**
// package.json scripts
{
"scripts": {
"security:audit": "npm audit --audit-level=high",
"security:secrets": "npx secretlint '**/*'",
"security:deps": "npx better-npm-audit audit"
}
}**Python:**
# Add to dev dependencies pip install safety bandit # Commands safety check # Check dependencies for vulnerabilities bandit -r src/ # Static security analysis
Security Check Script
Create `scripts/security-check.sh`:
#!/bin/bash
set -e
echo "Running security checks..."
# Check for secrets in staged files
echo "Checking for secrets..."
if command -v detect-secrets &> /dev/null; then
detect-secrets scan --baseline .secrets.baseline
fi
# Check .env is not staged
if git diff --cached --name-only | grep -E '^\.env$|^\.env\.' | grep -v '\.example$'; then
echo "ERROR: .env file is staged for commit!"
exit 1
fi
# Check for common secret patterns in staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
if echo "$STAGED_FILES" | xargs grep -l -E '(password|secret|api_key|apikey|token|private_key)\s*[:=]\s*["\047][^"\047]+["\047]' 2>/dev/null; then
echo "ERROR: Possible secrets found in staged files!"
exit 1
fi
# Language-specific checks
if [ -f "package.json" ]; then
echo "Checking npm dependencies..."
npm audit --audit-level=high || echo "Warning: npm audit found issues"
fi
if [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then
echo "Checking Python dependencies..."
if command -v safety &> /dev/null; then
safety check || echo "Warning: safety found issues"
fi
fi
echo "Security checks passed!"chmod +x scripts/security-check.sh
---
GitHub Actions Security Workflow
Create `.github/workflows/security.yml`:
name: Security
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run weekly on Monday at 9am UTC
- cron: '0 9 * * 1'
jobs:
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Detect secrets
uses: trufflesecurity/trufflehog@mainTurn Claude Code into a self-reviewing, test-enforced engineering system that remembers context across sessions — then route work across 13 models from a single dashboard.
Other skills on maggy.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about security.
- Which coding agents can use security?
- security installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

