ソース情報
- リポジトリ
- alinaqi/maggy
- ソースの最終更新活動
- 2026年4月7日 05:21
- 検出された SKILL.md の言語
- 英語
- スター
- 705
- フォーク
- 56
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/alinaqi/maggy --skill securityコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Universal coding patterns, constraints, TDD workflow, atomic todos
Multi-model validation council — auto-validate plans, architecture changes, and PRs via validate-plan/review before executing
Task-scoped memory lifecycle — typed MnemoGraph prevents lossy context compaction by treating facts/decisions/code-refs/handoffs as distinct node types with per-type eviction policies
SOC 職業分類に基づく
SKILL.md を表示中
| 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 best practices and automated security testing for all projects.
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.
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/
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=
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:
VITE_ prefix are server-onlyVITE_* vars are bundled into client codeValidate 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()
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
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..."
-v safety &> /dev/null;
safety check ||
chmod +x scripts/security-check.sh
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@main
with:
path: ./
base: ${{ github.event.pull_request.base.sha }}
head: ${{ github.event.pull_request.head.sha }}
dependency-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Node.js projects
- name: Setup Node
Never use string concatenation:
// BAD - SQL injection vulnerable
const user = await db.query(`SELECT * FROM users WHERE id = ${userId}`);
// GOOD - Parameterized query
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
// GOOD - Using ORM (Kysely, Prisma, Drizzle)
const user = await db.selectFrom('users').where('id', '=', userId).execute();
# BAD - SQL injection vulnerable
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# GOOD - Parameterized query
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# GOOD - Using ORM (SQLAlchemy)
user = session.query(User).filter(User.id == user_id).first()
// Always sanitize user input before rendering
import DOMPurify from 'dompurify';
// BAD - XSS vulnerable
element.innerHTML = userInput;
// GOOD - Sanitized
element.innerHTML = DOMPurify.sanitize(userInput);
// BEST - Use framework's built-in escaping (React does this by default)
return <div>{userInput}</div>; // Safe in React
// DANGER - Bypasses React's protection
return <div dangerouslySetInnerHTML={{ __html: userInput }} />; // Avoid!
// Validate ALL external input with Zod
import { z } from 'zod';
const CreateUserSchema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(100).regex(/^[a-zA-Z\s]+$/),
age: z.number().int().min(0).max(150),
});
// In route handler
app.post('/users', async (req, res) => {
const result = CreateUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: result.error });
}
// result.data is now typed and validated
});
import path from 'path';
// BAD - Path traversal vulnerable
const filePath = `./uploads/${req.params.filename}`;
// GOOD - Validate and sanitize path
const filename = path.basename(req.params.filename); // Strips ../
const filePath = path.join('./uploads', filename);
// Verify it's still within allowed directory
if (!filePath.startsWith(path.resolve('./uploads'))) {
throw new Error('Invalid path');
}
import jwt from 'jsonwebtoken';
// Token generation
function generateToken(userId: string): string {
return jwt.sign(
{ sub: userId },
process.env.JWT_SECRET!,
{
expiresIn: '15m', // Short-lived access tokens
algorithm: 'HS256',
}
);
}
// Token verification
function verifyToken(token: string): { sub: string } {
return jwt.verify(token, process.env.JWT_SECRET!, {
algorithms: ['HS256'], // Explicitly specify allowed algorithms
}) as { sub: string };
}
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // Minimum 10, recommended 12+
async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS);
}
async function verifyPassword(password: string, hash: string): Promise<boolean> {
return bcrypt.compare(password, hash);
}
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(password: str, hashed: str) -> bool:
return pwd_context.verify(password, hashed)
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per window
standardHeaders: true,
legacyHeaders: false,
});
// Apply to auth routes
app.use('/api/auth', rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 5, // 5 attempts per minute
message: 'Too many login attempts, please try again later',
}));
import helmet from 'helmet';
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
},
}));
Run before every release:
## Security Checklist
### Secrets & Environment
- [ ] No secrets in code (run detect-secrets)
- [ ] .env files in .gitignore
- [ ] .env.example exists with all required vars
- [ ] Environment validated at startup
### Dependencies
- [ ] npm audit / safety check passes
- [ ] No known vulnerabilities in dependencies
- [ ] Dependencies up to date (Dependabot enabled)
### Input Validation
- [ ] All API inputs validated with schema (Zod/Pydantic)
- [ ] File uploads restricted by type and size
- [ ] Path traversal prevented
### Authentication
- [ ] Passwords hashed with bcrypt (12+ rounds)
- [ ] JWTs use short expiration
- [ ] Rate limiting on auth endpoints
- [ ] Session tokens rotated on login
### Database
- [ ] Parameterized queries only
- [ ] Least privilege database user
- [ ] Connection strings not logged
### Headers & CORS
- [ ] Security headers enabled (helmet)
- [ ] CORS restricted to known origins
- [ ] HTTPS only in production
### Logging
- [ ] No secrets in logs
- [ ] No PII in logs (or properly masked)
- [ ] Failed auth attempts logged
VITE_*, NEXT_PUBLIC_*, or REACT_APP_* env vars (client-exposed!)dangerouslySetInnerHTML without sanitizationeval() or new Function() with user input* for CORS origins in production