{"id":"secure-code-guardian","name":"secure-code-guardian","summary":"認証・認可の実装、ユーザー入力の保護、OWASPトップ10の脆弱性防止など、bcrypt/argon2によるパスワードハッシュ化、パラメータ化された文でSQLクエリをサニタイズする、CORS/CSPヘッダーの設定、validatなどのカスタムセキュリティ実装を含みます。","body":"# Secure Code Guardian\n\n## Core Workflow\n\n1. **Threat model** — Identify attack surface and threats\n2. **Design** — Plan security controls\n3. **Implement** — Write secure code with defense in depth; see code examples below\n4. **Validate** — Test security controls with explicit checkpoints (see below)\n5. **Document** — Record security decisions\n\n### Validation Checkpoints\n\nAfter each implementation step, verify:\n\n- **Authentication**: Test brute-force protection (lockout/rate limit triggers), session fixation resistance, token expiration, and invalid-credential error messages (must not leak user existence).\n- **Authorization**: Verify horizontal and vertical privilege escalation paths are blocked; test with tokens belonging to different roles/users.\n- **Input handling**: Confirm SQL injection payloads (`' OR 1=1--`) are rejected; confirm XSS payloads (`<script>alert(1)</script>`) are escaped or rejected.\n- **Headers/CORS**: Validate with a security scanner (e.g., `curl -I`, Mozilla Observatory) that security headers are present and CORS origin allowlist is correct.\n\n## Reference Guide\n\nLoad detailed guidance based on context:\n\n| Topic | Reference | Load When |\n|-------|-----------|-----------|\n| OWASP | `references/owasp-prevention.md` | OWASP Top 10 patterns |\n| Authentication | `references/authentication.md` | Password hashing, JWT |\n| Input Validation | `references/input-validation.md` | Zod, SQL injection |\n| XSS/CSRF | `references/xss-csrf.md` | XSS prevention, CSRF |\n| Headers | `references/security-headers.md` | Helmet, rate limiting |\n\n## Constraints\n\n### MUST DO\n- Hash passwords with bcrypt/argon2 (never MD5/SHA-1/unsalted hashes)\n- Use parameterized queries (never string-interpolated SQL)\n- Validate and sanitize all user input before use\n- Implement rate limiting on auth endpoints\n- Set security headers (CSP, HSTS, X-Frame-Options)\n- Log security events (failed auth, privilege escalation attempts)\n- Store secrets in environment variables or secret managers (never in source code)\n\n### MUST NOT DO\n- Store passwords in plaintext or reversibly encrypted form\n- Trust user input without validation\n- Expose sensitive data in logs or error responses\n- Use weak or deprecated algorithms (MD5, SHA-1, DES, ECB mode)\n- Hardcode secrets or credentials in code\n\n## Code Examples\n\n### Password Hashing (bcrypt)\n\n```typescript\nimport bcrypt from 'bcrypt';\n\nconst SALT_ROUNDS = 12; // minimum 10; 12 balances security and performance\n\nexport async function hashPassword(plaintext: string): Promise<string> {\n  return bcrypt.hash(plaintext, SALT_ROUNDS);\n}\n\nexport async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {\n  return bcrypt.compare(plaintext, hash);\n}\n```\n\n### Parameterized SQL Query (Node.js / pg)\n\n```typescript\n// NEVER: `SELECT * FROM users WHERE email = '${email}'`\n// ALWAYS: use positional parameters\nimport { Pool } from 'pg';\nconst pool = new Pool();\n\nexport async function getUserByEmail(email: string) {\n  const { rows } = await pool.query(\n    'SELECT id, email, role FROM users WHERE email = $1',\n    [email]  // value passed separately — never interpolated\n  );\n  return rows[0] ?? null;\n}\n```\n\n### Input Validation with Zod\n\n```typescript\nimport { z } from 'zod';\n\nconst LoginSchema = z.object({\n  email: z.string().email().max(254),\n  password: z.string().min(8).max(128),\n});\n\nexport function validateLoginInput(raw: unknown) {\n  const result = LoginSchema.safeParse(raw);\n  if (!result.success) {\n    // Return generic error — never echo raw input back\n    throw new Error('Invalid credentials format');\n  }\n  return result.data;\n}\n```\n\n### JWT Validation\n\n```typescript\nimport jwt from 'jsonwebtoken';\n\nconst JWT_SECRET = process.env.JWT_SECRET!; // never hardcode\n\nexport function verifyToken(token: string): jwt.JwtPayload {\n  // Throws if expired, tampered, or wrong algorithm\n  const payload = jwt.verify(token, JWT_SECRET, {\n    algorithms: ['HS256'],   // explicitly allowlist algorithm\n    issuer: 'your-app',\n    audience: 'your-app',\n  });\n  if (typeof payload === 'string') throw new Error('Invalid token payload');\n  return payload;\n}\n```\n\n### Securing an Endpoint — Full Flow\n\n```typescript\nimport express from 'express';\nimport rateLimit from 'express-rate-limit';\nimport helmet from 'helmet';\n\nconst app = express();\napp.use(helmet()); // sets CSP, HSTS, X-Frame-Options, etc.\napp.use(express.json({ limit: '10kb' })); // limit payload size\n\nconst authLimiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  max: 10,                   // 10 attempts per window per IP\n  standardHeaders: true,\n  legacyHeaders: false,\n});\n\napp.post('/api/login', authLimiter, async (req, res) => {\n  // 1. Validate input\n  const { email, password } = validateLoginInput(req.body);\n\n  // 2. Authenticate — parameterized query, constant-time compare\n  const user = await getUserByEmail(email);\n  if (!user || !(await verifyPassword(password, user.passwordHash))) {\n    // Generic message — do not reveal whether email exists\n    return res.status(401).json({ error: 'Invalid credentials' });\n  }\n\n  // 3. Authorize — issue scoped, short-lived token\n  const token = jwt.sign(\n    { sub: user.id, role: user.role },\n    JWT_SECRET,\n    { algorithm: 'HS256', expiresIn: '15m', issuer: 'your-app', audience: 'your-app' }\n  );\n\n  // 4. Secure response — token in httpOnly cookie, not body\n  res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'strict' });\n  return res.json({ message: 'Authenticated' });\n});\n```\n\n## Output Templates\n\nWhen implementing security features, provide:\n1. Secure implementation code\n2. Security considerations noted\n3. Configuration requirements (env vars, headers)\n4. Testing recommendations\n\n## Knowledge Reference\n\nOWASP Top 10, bcrypt/argon2, JWT, OAuth 2.0, OIDC, CSP, CORS, rate limiting, input validation, output encoding, encryption (AES, RSA), TLS, security headers\n\n[Documentation](https://jeffallan.github.io/claude-skills/skills/security/secure-code-guardian/)","author":"@Jeffallan","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/Jeffallan/claude-skills/tree/main/skills/secure-code-guardian","license":"MIT","category":"writing","lang":"en","tokens":1438,"stars":0,"calls30d":0,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/authentication.md","size":3349,"sha256":"4d680ac47602955de09a4bb248346a91b96158d0b7e23de4fe20ecfda2ff8ac2"},{"path":"references/input-validation.md","size":3372,"sha256":"2f227b437b0d1184ad557c3ba48bf6e0db4df43c8949c9c0fc923c69847a040a"},{"path":"references/owasp-prevention.md","size":3335,"sha256":"4baed17eeefd365c1b46cf54e0915e99ce85666b345faf40dd9c6bf9e33372b1"},{"path":"references/security-headers.md","size":3020,"sha256":"59333cf6d3a13b8675d98afd0888e224a1e6b644f755b08a46ebcef3fb6be281"},{"path":"references/xss-csrf.md","size":3213,"sha256":"4d9976faed6ff05ce2677cdccee1df0be2980375fcdc6151ea59553fce5ca470"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[{"code":"code.eval","kind":"dangerous-code","where":"references/input-validation.md:80","excerpt":"exec(","message":"evaluates code at runtime","severity":"warn"},{"code":"code.eval","kind":"dangerous-code","where":"references/owasp-prevention.md:33","excerpt":"exec(","message":"evaluates code at runtime","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["api.example.com","app.example.com","jeffallan.github.io"]}}