secure-code-guardian について
アプリケーションのセキュリティ対策を計画、実装、検証する開発者向けスキルです。脅威モデリングに加え、認証、入力処理、認可、セキュリティヘッダーを扱います。
主な機能
- 01脅威モデリングとセキュリティ設計
- 02認証と認可のチェック
- 03入力検証とサニタイズ
- 04セキュリティヘッダーとレート制限
- 05セキュリティ判断の記録
活用シーン
- 01認証とセッション制御のレビュー
- 02インジェクションとXSS対策のテスト
- 03認可境界とセキュリティヘッダーの確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jeffallan/ claude-skills --skill secure-code-guardianインストール後、Claude Code で/secure-code-guardianを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/authentication.mdinput-validation.mdowasp-prevention.mdsecurity-headers.mdxss-csrf.md詳細
セキュアコードガーディアン
コアワークフロー
- 脅威モデル — 攻撃対象領域と脅威を特定します
- 設計 — セキュリティ制御を計画します
- 実装 — 多層防御でセキュアなコードを記述します。以下のコード例を参照してください
- 検証 — 明示的なチェックポイントでセキュリティ制御をテストします(以下を参照)
- 文書化 — セキュリティ上の決定を記録します
検証チェックポイント
各実装ステップの後に、次の項目を検証します。
- 認証:総当たり攻撃対策(ロックアウト/レート制限の動作)、セッション固定攻撃への耐性、トークンの有効期限、無効な認証情報に対するエラーメッセージ(ユーザーの存在を漏らしてはなりません)をテストします。
- 認可:水平および垂直方向の権限昇格経路が遮断されていることを確認します。異なるロール/ユーザーに属するトークンでテストします。
- 入力処理:SQL インジェクションのペイロード(
' OR 1=1--)が拒否されることを確認します。XSS のペイロード(<script>alert(1)</script>)がエスケープまたは拒否されることを確認します。 - ヘッダー/CORS:セキュリティスキャナー(例:
curl -I、Mozilla Observatory)を使用して、セキュリティヘッダーが設定されていること、および CORS のオリジン許可リストが正しいことを検証します。
リファレンスガイド
状況に応じて、詳細なガイダンスを読み込みます。
| トピック | リファレンス | 読み込むタイミング |
|---|---|---|
| OWASP | references/owasp-prevention.md | OWASP Top 10 のパターン |
| 認証 | references/authentication.md | パスワードのハッシュ化、JWT |
| 入力検証 | references/input-validation.md | Zod、SQL インジェクション |
| XSS/CSRF | references/xss-csrf.md | XSS 対策、CSRF |
| ヘッダー | references/security-headers.md | Helmet、レート制限 |
制約事項
必ず実施すること
- パスワードは bcrypt/argon2 でハッシュ化します(MD5/SHA-1/ソルトなしのハッシュは決して使用しません)
- パラメーター化クエリを使用します(文字列補間した SQL は決して使用しません)
- すべてのユーザー入力を使用前に検証し、サニタイズします
- 認証エンドポイントにレート制限を実装します
- セキュリティヘッダー(CSP、HSTS、X-Frame-Options)を設定します
- セキュリティイベント(認証の失敗、権限昇格の試行)をログに記録します
- シークレットは環境変数またはシークレットマネージャーに保存します(ソースコードには決して保存しません)
絶対にしてはならないこと
- パスワードを平文または元に戻せる暗号化形式で保存する
- 検証せずにユーザー入力を信頼する
- ログやエラーレスポンスで機密データを漏らす
- 脆弱または非推奨のアルゴリズム(MD5、SHA-1、DES、ECB モード)を使用する
- シークレットや認証情報をコードにハードコードする
コード例
パスワードのハッシュ化(bcrypt)
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // minimum 10; 12 balances security and performance
export async function hashPassword(plaintext: string): Promise<string> {
return bcrypt.hash(plaintext, SALT_ROUNDS);
}
export async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {
return bcrypt.compare(plaintext, hash);
}
パラメーター化 SQL クエリ(Node.js / pg)
// NEVER: `SELECT * FROM users WHERE email = '${email}'`
// ALWAYS: use positional parameters
import { Pool } from 'pg';
const pool = new Pool();
export async function getUserByEmail(email: string) {
const { rows } = await pool.query(
'SELECT id, email, role FROM users WHERE email = $1',
[email] // value passed separately — never interpolated
);
return rows[0] ?? null;
}
Zod による入力検証
import { z } from 'zod';
const LoginSchema = z.object({
email: z.string().email().max(254),
password: z.string().min(8).max(128),
});
export function validateLoginInput(raw: unknown) {
const result = LoginSchema.safeParse(raw);
if (!result.success) {
// Return generic error — never echo raw input back
throw new Error('Invalid credentials format');
}
return result.data;
}
JWT の検証
import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET!; // never hardcode
export function verifyToken(token: string): jwt.JwtPayload {
// Throws if expired, tampered, or wrong algorithm
const payload = jwt.verify(token, JWT_SECRET, {
algorithms: ['HS256'], // explicitly allowlist algorithm
issuer: 'your-app',
audience: 'your-app',
});
if (typeof payload === 'string') throw new Error('Invalid token payload');
return payload;
}
エンドポイントの保護 — 全体の流れ
import express from 'express';
import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
const app = express();
app.use(helmet()); // sets CSP, HSTS, X-Frame-Options, etc.
app.use(express.json({ limit: '10kb' })); // limit payload size
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // 10 attempts per window per IP
standardHeaders: true,
legacyHeaders: false,
});
app.post('/api/login', authLimiter, async (req, res) => {
// 1. Validate input
const { email, password } = validateLoginInput(req.body);
// 2. Authenticate — parameterized query, constant-time compare
const user = await getUserByEmail(email);
if (!user || !(await verifyPassword(password, user.passwordHash))) {
// Generic message — do not reveal whether email exists
return res.status(401).json({ error: 'Invalid credentials' });
}
// 3. Authorize — issue scoped, short-lived token
const token = jwt.sign(
{ sub: user.id, role: user.role },
JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '15m', issuer: 'your-app', audience: 'your-app' }
);
// 4. Secure response — token in httpOnly cookie, not body
res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'strict' });
return res.json({ message: 'Authenticated' });
});
出力テンプレート
セキュリティ機能を実装する際は、次の内容を提示します。
- セキュアな実装コード
- 留意すべきセキュリティ上の考慮事項
- 設定要件(環境変数、ヘッダー)
- テストに関する推奨事項
ナレッジリファレンス
OWASP Top 10、bcrypt/argon2、JWT、OAuth 2.0、OIDC、CSP、CORS、レート制限、入力検証、出力エンコーディング、暗号化(AES、RSA)、TLS、セキュリティヘッダー
Synergetic Solutions のプリンシパルコンサルタント、@jeffallan が保守しています
コメント
Markdown 対応