mcpField
S
security-audit

security-audit

github.com/aakash-dharセキュリティ0160 回インストール36 週間前に更新
リポジトリ

security-audit について

security-auditは、一般的なアプリケーションやインフラのリスクを対象とするコードセキュリティレビュー用スキルです。秘密情報、インジェクション、アクセス制御、データ漏えい、依存関係、技術スタック固有の確認項目とコマンド例を示します。

主な機能

  1. 01秘密情報と認証情報のスキャン
  2. 02インジェクションと入力検証の確認
  3. 03認証と認可のレビュー
  4. 04データ漏えいと暗号化の確認
  5. 05依存関係とHTTPヘッダーの確認
  6. 06フレームワーク別レビュー指針

活用シーン

  1. 01コードベースの認証情報漏えいを監査
  2. 02APIコードのインジェクションやアクセス制御を確認
  3. 03アプリ設定と依存関係を点検

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/aakash-dhar/claude-skills --skill security-audit

インストール後、Claude Code で/security-auditを入力して読み込まれたか確認します。

詳細

セキュリティ監査スキル

コードのセキュリティを監査するときは、この体系的な手順に従ってください。すべての検出事項を重大なものとして扱ってください。脆弱性が1つあるだけで、システム全体が侵害される可能性があります。

1. シークレットと認証情報

コードベース全体をスキャンして、公開されているシークレットを探します。

  • ソースコードにハードコードされた API キー、トークン、パスワード
  • Git にコミットされた設定ファイル内のシークレット(.env、config.json、settings.py)
  • ログ内のシークレット — console.log、logger.info などで出力される機密データ
  • エラーメッセージ内のシークレット — 内部情報が漏れるスタックトレースやエラーレスポンス
  • コメント内のシークレット — TODO やコメントアウトされたコードに残された古い認証情報
  • Git 履歴内のシークレット — シークレットがコミット後に削除されていないか確認します(履歴には残っています)

確認コマンド:

# Search for common secret patterns
grep -rn "password\|secret\|api_key\|apikey\|token\|private_key\|AWS_SECRET\|DATABASE_URL" --include="*.ts" --include="*.js" --include="*.py" --include="*.env" --include="*.json" --include="*.yaml" --include="*.yml" .

# Check for .env files committed
git ls-files | grep -i "\.env"

# Check git history for secrets
git log --all --diff-filter=D -- "*.env" "*.pem" "*.key"

確認事項:

  • .gitignore が設定されており、.env、*.pem、*.key、*.p12 が含まれていますか?
  • シークレットはファイルではなく、環境変数またはボールトから読み込まれていますか?
  • 実際のシークレットではなく、プレースホルダー値を使った .env.example がありますか?

2. インジェクション攻撃

SQL インジェクション
// 🔴 VULNERABLE — string concatenation in query
const user = await db.query(`SELECT * FROM users WHERE id = '${req.params.id}'`);

// ✅ SAFE — parameterized query
const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
NoSQL インジェクション
// 🔴 VULNERABLE — user input directly in query object
const user = await User.find({ username: req.body.username });

// ✅ SAFE — explicitly cast to string
const user = await User.find({ username: String(req.body.username) });
コマンドインジェクション
// 🔴 VULNERABLE — user input in shell command
exec(`convert ${req.body.filename} output.png`);

// ✅ SAFE — use execFile with arguments array
execFile('convert', [sanitizedFilename, 'output.png']);
XSS(クロスサイトスクリプティング)
// 🔴 VULNERABLE — unsanitized HTML rendering
element.innerHTML = userInput;
// React: dangerouslySetInnerHTML={{ __html: userInput }}

// ✅ SAFE — use textContent or sanitize
element.textContent = userInput;
// React: use DOMPurify.sanitize() before dangerouslySetInnerHTML
パストラバーサル
// 🔴 VULNERABLE — user controls file path
const file = fs.readFileSync(`./uploads/${req.params.filename}`);

// ✅ SAFE — resolve and validate path stays within allowed directory
const safePath = path.resolve('./uploads', req.params.filename);
if (!safePath.startsWith(path.resolve('./uploads'))) throw new Error('Invalid path');
テンプレートインジェクション
  • ユーザー入力がテンプレートエンジン(Jinja2、EJS、Handlebars)に直接渡されていないか確認します
  • 自動エスケープが有効になっていることを確認します

3. 認証と認可

認証の不備
  • パスワード要件が弱い — 最小文字数、複雑さ、漏えいチェックがない
  • ログインエンドポイントにレート制限がない(ブルートフォース攻撃のリスク)
  • ログイン試行失敗後のアカウントロックアウトがない
  • パスワードの保存方法が安全でない — 平文、MD5、SHA1(適切なコスト設定で bcrypt/argon2 を使用してください)
  • 機密性の高い操作で MFA がない
  • URL 内のセッショントークン — トークンはヘッダーまたは httpOnly Cookie に保存してください
  • セッションの有効期限がない — 期限切れにならないトークン
認可の不備
  • 認可チェックがない — ユーザー権限を確認せずにエンドポイントへアクセスできる
  • IDOR(安全でない直接オブジェクト参照) — ID を変更して他のユーザーのデータにアクセスできる
  • 権限昇格 — 一般ユーザーが管理者用エンドポイントにアクセスできる
  • リソース所有者のチェックがない — ユーザー A がユーザー B のデータを変更できる
// 🔴 VULNERABLE — IDOR: no ownership check
app.get('/api/orders/:id', async (req, res) => {
  const order = await Order.findById(req.params.id);
  res.json(order);
});

// ✅ SAFE — verify ownership
app.get('/api/orders/:id', async (req, res) => {
  const order = await Order.findById(req.params.id);
  if (order.userId !== req.user.id) return res.status(403).json({ error: 'Forbidden' });
  res.json(order);
});

4. データ漏えい

  • API レスポンス内の機密データ — パスワード、トークン、SSN、クレジットカード番号全桁を返している
  • 本番環境で詳細すぎるエラーメッセージ — スタックトレース、データベースの詳細、内部パス
  • フィールドのフィルタリングがない — 特定のフィールドではなくデータベースオブジェクト全体を返している
  • クライアント側ストレージ内の機密データ — localStorage 内のトークン(httpOnly Cookie を使用してください)
  • ログ内の PII — 氏名、メールアドレス、IP アドレスがマスキングされずに記録されている
  • データ暗号化がない — 機密データが保存時に暗号化されていない
  • CORS の設定ミス — 認証が必要なエンドポイントで Access-Control-Allow-Origin: * を設定している
// 🔴 VULNERABLE — leaking sensitive fields
res.json(user);

// ✅ SAFE — explicit field selection
res.json({
  id: user.id,
  name: user.name,
  email: user.email,
});

5. 入力検証

  • 検証がない — リクエストボディ、パラメーター、クエリー文字列をチェックしていない
  • 型の混同 — 数値を想定しているのに文字列を受け入れている
  • 長さ制限がない — DoS を引き起こす可能性がある、上限のない入力
  • ファイルアップロードの検証がない — ファイルの種類、サイズ、内容をチェックしていない
  • 正規表現 DoS(ReDoS) — 悪意のある入力による壊滅的なバックトラッキング
  • Content-Type の検証がない — 想定外の Content-Type を受け入れている

確認事項:

  • 検証ライブラリ(Zod、Joi、class-validator、Pydantic)を使用していますか?
  • すべての API エンドポイントで、処理前に入力を検証していますか?
  • ファイルアップロードは種類とサイズが制限され、マルウェアスキャンが実施されていますか?

6. 依存関係

次のチェックを実行します:

# Node.js
npm audit
# or
npx better-npm-audit audit

# Python
pip audit
# or
safety check

# Check for outdated packages
npm outdated
pip list --outdated

確認項目:

  • 依存関係に既知の CVE がある
  • 既知の脆弱性がある古いパッケージ
  • メンテナンスが放棄されたパッケージ — 2年以上更新されていない
  • タイポスクワッティングのリスク — パッケージ名が正しいことを確認します
  • 過剰な権限 — 必要以上のアクセスを要求するパッケージ
  • ロックファイルの有無 — package-lock.json または yarn.lock がコミットされている

7. HTTP セキュリティヘッダー

次のヘッダーが設定されているか確認します。

  • Content-Security-Policy — XSS とデータインジェクションを防止します
  • Strict-Transport-Security — HTTPS を強制します
  • X-Content-Type-Options: nosniff — MIME タイプの推測を防止します
  • X-Frame-Options: DENY — クリックジャッキングを防止します
  • Referrer-Policy — リファラー情報を制御します
  • Permissions-Policy — ブラウザー機能を制限します
# Check response headers
curl -I https://your-app.com

8. 暗号化

  • 脆弱なハッシュ化 — パスワードに MD5 または SHA1 を使用している(bcrypt、scrypt、または argon2 を使用してください)
  • 脆弱な暗号化 — DES、RC4、ECB モードを使用している(AES-256-GCM を使用してください)
  • 暗号化キーのハードコード — キーは環境変数またはボールトに保存する必要があります
  • TLS の欠如 — 機密データに HTTP 接続を使用している
  • 脆弱な JWT — alg: none を使用している、または短いシークレットで HS256 を使用している
  • 予測可能な乱数値 — トークンに Math.random() を使用している(crypto.randomBytes を使用してください)
// 🔴 VULNERABLE — predictable token
const token = Math.random().toString(36);

// ✅ SAFE — cryptographically secure
const token = crypto.randomBytes(32).toString('hex');

9. インフラストラクチャと設定

  • 本番環境でのデバッグモード — 詳細なエラー、スタックトレース、デバッグエンドポイントが有効になっている
  • デフォルトの認証情報 — admin/admin、root/root が引き続き有効になっている
  • 不要なポートの開放 — データベースのポートがインターネットに公開されている
  • レート制限の欠如 — DoS への防御がない
  • リクエストサイズ制限の欠如 — 大きなペイロードによって OOM が発生する
  • 安全でない CORS — 認証済みエンドポイントでワイルドカードオリジンを使用している
  • CSRF 対策の欠如 — 状態を変更するエンドポイントに CSRF トークンがない

10. スタック固有のチェック

Node.js / Express
  • helmet ミドルウェアがインストールされ、設定されていることを確認します
  • express.json() にサイズ制限が設定されていることを確認します:express.json({ limit: '10kb' })
  • Cookie の設定を確認します:httpOnly、secure、sameSite
  • オブジェクトのマージでプロトタイプ汚染が発生しないか確認します(lodash.merge、ユーザー入力を用いた Object.assign)
  • child_process の呼び出しで、すべての入力がサニタイズされることを確認します
  • 認証エンドポイントに express-rate-limit が適用されていることを確認します
  • イベントエミッターのメモリリーク(removeListener の呼び出し漏れ)がないか確認します
  • ユーザー入力に対して eval()、Function()、または vm.runInNewContext() が使用されていないことを確認します
Python / Django
  • 本番環境の設定で DEBUG = False になっていることを確認します
  • ALLOWED_HOSTS が ['*'] になっていないことを確認します
  • CSRF ミドルウェアが有効になっていることを確認します
  • パラメーター化されていない raw SQL クエリがないか確認します
  • SECRET_KEY がハードコードされず、環境から読み込まれていることを確認します
  • ユーザー入力の pickle デシリアライズ(RCE のリスク)がないか確認します
  • django-cors-headers が特定のオリジンを使って設定されていることを確認します
  • 保護対象のすべてのビューに @login_required または権限クラスが設定されていることを確認します
  • 安全でない YAML の読み込み(Loader=SafeLoader を指定しない yaml.load())がないか確認します
  • 本番環境で SECURE_SSL_REDIRECT、SESSION_COOKIE_SECURE、CSRF_COOKIE_SECURE が True になっていることを確認します
Python / Flask
  • app.secret_key がハードコードされていないことを確認します
  • 保護対象のルートに @login_required デコレーターが設定されていない箇所がないか確認します
  • Jinja2 の自動エスケープが有効になっていることを確認します(Flask ではデフォルトで有効ですが、カスタムテンプレートを確認してください)
  • セキュリティヘッダーの設定に flask-talisman などが使われていることを確認します
  • 認証エンドポイントと機密性の高いエンドポイントに flask-limiter が適用されていることを確認します
  • 安全でないファイルアップロード(werkzeug の secure_filename() の使用漏れ)がないか確認します
React / Next.js
  • サニタイズされていない入力に対して dangerouslySetInnerHTML が使われていないか確認します
  • トークンが localStorage に保存されていないことを確認します(httpOnly Cookie を使用してください)
  • クライアント側のコードやバンドルに機密データが含まれていないか確認します
  • 環境変数で NEXT_PUBLIC_ 接頭辞を使っているのが、機密性のない値のみであることを確認します
  • URL パラメーターを使ったオープンリダイレクトがないか確認します
  • API ルートに適切な認証ミドルウェアが設定されていることを確認します
  • Server Actions で入力が検証され、認可がチェックされていることを確認します
  • getServerSideProps の機密データが pageProps に漏えいしていないか確認します
  • next.config.js に適切なセキュリティヘッダーが設定されていることを確認します
  • 本番環境でソースマップが公開されていないか確認します
Vue / Nuxt
  • サニタイズされていないユーザー入力に対する v-html の使用を確認します
  • トークンが localStorage に保存されていないことを確認します
  • nuxt.config に公開されているランタイム設定のシークレットがないか確認します
  • サーバーミドルウェアに認証チェックがあることを確認します
  • useAsyncData または useFetch を介して、サーバーからクライアントに機密データが漏れていないか確認します
Ruby on Rails
  • 本番環境で config.force_ssl = true が設定されていることを確認します
  • ユーザー提供コンテンツに対する html_safe または raw の使用を確認します
  • protect_from_forgery が有効になっていることを確認します
  • マスアサインメントの脆弱性(strong_parameters の不足)がないか確認します
  • has_secure_password が bcrypt を使用していることを確認します
  • ユーザー入力に対する安全でない send() または constantize() の使用を確認します
  • config.filter_parameters に機密フィールドが含まれていることを確認します
Go
  • クエリで使用される fmt.Sprintf に SQL インジェクションの脆弱性がないか確認します(パラメーター化クエリを使用してください)
  • TLS 設定で TLS 1.2 以上が使用されていることを確認します
  • http.ServeFile または os.Open にパストラバーサルの脆弱性がないか確認します
  • 適切なエラー処理が行われていることを確認します(エラーレスポンスに機密データを含めないでください)
  • 共有状態における競合状態(ミューテックスの不足)がないか確認します
  • セキュリティ上重要な値には math/rand ではなく crypto/rand が使用されていることを確認します
  • パニックを引き起こす可能性のある、チェックされていない型アサーションがないか確認します
Java / Spring Boot
  • Spring Security が設定されており、機密性の高いエンドポイントで permitAll() が使用されていないことを確認します
  • 文字列連結を使った @Query アノテーションに SQL インジェクションの脆弱性がないか確認します
  • CSRF 保護が有効になっていることを確認します(Spring Security のデフォルト設定)
  • デシリアライゼーションの脆弱性(Jackson、Java シリアライゼーション)がないか確認します
  • リクエスト本文のパラメーターに @Valid アノテーションが付いていることを確認します
  • application.properties または application.yml にハードコードされた認証情報がないか確認します
  • actuator エンドポイントが保護され、一般公開されていないことを確認します
  • 依存関係に Log4j/Log4Shell の脆弱性がないか確認します
PHP / Laravel
  • 本番環境の .env で APP_DEBUG=false が設定されていることを確認します
  • パラメーターバインディングなしで実行される生の SQL クエリがないか確認します
  • すべての POST/PUT/DELETE ルートに CSRF ミドルウェアが適用されていることを確認します
  • ユーザー入力に対する eval()、exec()、system() の使用を確認します
  • ファイルアップロードに検証ルール(MIME タイプ、最大サイズ)が適用されていることを確認します
  • 機密性の高いルートが Auth::check() またはミドルウェアのガードによって保護されていることを確認します
  • $fillable または $guarded によって mass assignment が保護されていることを確認します
  • ユーザー入力に対する {!! !!} を使った安全でない Blade レンダリングがないか確認します
モバイル(React Native / Flutter)
  • AsyncStorage/SharedPreferences に機密データが保存されていないか確認します(暗号化ストレージを使用してください)
  • API キーがアプリのバンドルに埋め込まれていないことを確認します
  • 機密性の高い API 呼び出しで証明書ピンニングが行われていることを確認します
  • ディープリンクハンドラーが、ナビゲーションの前に入力を検証していることを確認します
  • アプリのログ(adb logcat / Console.app で表示可能)に機密データが含まれていないか確認します
  • 生体認証がサーバー側で適切に検証されていることを確認します
  • 信頼されていないコンテンツに対して JavaScript を有効にするなど、安全でない WebView 設定がないか確認します
決済セキュリティ
  • PCI DSS のコンプライアンス要件を満たしていることを確認します
  • クレジットカード番号の全桁が保存またはログに記録されないことを確認します
  • 決済処理でトークナイゼーションが使用されていることを確認します
  • Webhook エンドポイントが署名を検証していることを確認します
  • 返金エンドポイントに適切な認可とレート制限が設定されていることを確認します
  • 決済金額がサーバー側で検証されていることを確認します(クライアントからの値を信頼しないでください)
  • 決済確認ページの URL に取引の詳細が露出していないことを確認します
  • 決済処理に競合状態(多重請求のリスク)がないか確認します
AWS / クラウドインフラストラクチャ
  • 過度に許可範囲の広い IAM ポリシー("Action": "*"、"Resource": "*")がないか確認します
  • S3 バケットが一般公開されていないことを確認します
  • 暗号化されていない RDS インスタンスまたは EBS ボリュームがないか確認します
  • セキュリティグループで機密性の高いポートへの 0.0.0.0/0 からのアクセスが許可されていないことを確認します
  • ハードコードされた AWS 認証情報がないか確認します(代わりに IAM ロールを使用してください)
  • CloudTrail のロギングが有効になっていることを確認します
  • 機密性の高いサービスを実行している EC2 インスタンスが一般公開されていないか確認します
  • シークレットが AWS Secrets Manager または Parameter Store に保存されていることを確認します
Docker/コンテナー
  • root として実行されているコンテナーを確認します
  • ベースイメージが信頼できるソースのものであり、特定のバージョンに固定されていることを確認します
  • Docker イメージにシークレットが組み込まれていないか確認します(ビルドシークレットまたは実行時環境変数を使用してください)
  • .dockerignore で .env、.git、node_modules が除外されていることを確認します
  • 本番用イメージに不要なパッケージがインストールされていないか確認します
  • ヘルスチェックが設定されていることを確認します
  • 公開すべきでないポートが公開されていないか確認します

出力形式

見つかった脆弱性ごとに、次の形式で記載します。

[重大度] カテゴリー — ファイル:行

  • 脆弱性:問題の内容
  • リスク:攻撃者がこれを利用して何を実行できるか
  • 実証:悪用方法(チーム内での理解を目的とします)
  • 修正:問題を解決するための具体的なコード変更
  • 参考情報:該当する場合は CWE または OWASP のリンク
// vulnerable code
...

// fixed code
...

重大度のレベル:

  • 🔴 CRITICAL — 現実に悪用可能です。データ侵害、RCE、またはシステム全体の侵害につながります。直ちに修正してください。
  • 🟠 HIGH — ある程度の労力をかければ悪用可能です。重大なデータ漏えいや権限昇格につながります。次回のデプロイ前に修正してください。
  • 🟡 MEDIUM — 悪用には特定の条件が必要です。現在のスプリント中に修正してください。
  • 🟢 LOW — 軽微な問題、または多層防御の改善です。都合のよいときに修正してください。

まとめ

すべての監査の最後に、次の項目を記載してください。

  1. リスク評価 — 全体的なセキュリティ態勢(Critical/High/Medium/Low リスク)
  2. 重大な指摘事項の数 — 直ちに対応が必要な問題の数
  3. 最も危険な問題トップ 3 — 悪用の容易さと影響度に基づく順位
  4. すぐにできる改善 — 30 分未満で実施でき、リスクを大幅に低減できる修正
  5. 推奨事項 — WAF、セキュリティヘッダー、CI での依存関係スキャンなど、中長期的な改善
  6. 適切に実施できていること — 維持すべき、すでに導入されているセキュリティ対策

コメント