mcpField
S
security

security

github.com/motormetricsセキュリティ2257 回インストール今日更新
リポジトリ

security について

securityは、アプリケーションコードと依存関係のセキュリティレビューを支援する開発スキルです。監査コマンドや例、一般的なWebリスクを扱うチェックリストを備えています。

主な機能

  1. 01pnpm auditとSnykによる確認
  2. 02OWASP Top 10のレビュー指針
  3. 03Zodによる入力検証
  4. 04アクセス制御とインジェクション対策の例
  5. 05CORSとセキュリティヘッダーの指針
  6. 06コードとCIのセキュリティチェックリスト

活用シーン

  1. 01依存関係の既知の脆弱性を確認
  2. 02認可と入力処理をレビュー
  3. 03CORSとレスポンスヘッダーを強化
  4. 04CIにセキュリティチェックを追加

インストール

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

$npx skills add https://github.com/motormetrics/motormetrics --skill security

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

詳細

セキュリティスキル

依存関係のスキャン

pnpm audit
# Run audit
pnpm audit

# Only high/critical
pnpm audit --audit-level=high

# Auto-fix
pnpm audit --fix

# JSON report
pnpm audit --json > audit.json
脆弱性の修正

直接依存関係: pnpm-workspace.yaml のカタログでバージョンを更新します

間接依存関係:

# Find dependency chain
pnpm why vulnerable-package

# Use overrides as last resort
# package.json
{
  "pnpm": {
    "overrides": {
      "vulnerable-package": "^3.1.0"
    }
  }
}
Snyk
snyk auth          # Authenticate
snyk test          # Test for vulnerabilities
snyk monitor       # Monitor for new vulnerabilities
snyk fix           # Auto-fix

OWASP Top 10 のチェック

1. アクセス制御の不備
// ❌ No authorization
export async function deletePost(postId: string) {
  await db.delete(posts).where(eq(posts.id, postId));
}

// ✅ With authorization
export async function deletePost(postId: string, userId: string) {
  const post = await db.query.posts.findFirst({ where: eq(posts.id, postId) });
  if (post.authorId !== userId) throw new Error("Unauthorized");
  await db.delete(posts).where(eq(posts.id, postId));
}
2. インジェクションの防止
// ❌ SQL Injection
const query = `SELECT * FROM users WHERE id = ${userId}`;

// ✅ Parameterized query (Drizzle ORM)
const user = await db.query.users.findFirst({ where: eq(users.id, userId) });
3. XSS の防止

React はデフォルトでコンテンツをエスケープします。HTML をレンダリングする場合:

  • レンダリング前に sanitize-html ライブラリでサニタイズします
  • 信頼できないコンテンツを直接レンダリングしないでください
4. レート制限
import { Ratelimit } from "@upstash/ratelimit";
import { redis } from "@sgcarstrends/utils";

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(5, "15 m"),
});

export async function login(email: string, password: string, ip: string) {
  const { success } = await ratelimit.limit(ip);
  if (!success) throw new Error("Too many login attempts");
  return verifyCredentials(email, password);
}
5. パスワードのセキュリティ
import bcrypt from "bcrypt";

// ✅ Hash passwords
const hashedPassword = await bcrypt.hash(password, 10);

// ✅ Strong password validation
const passwordSchema = z.string()
  .min(12)
  .regex(/[A-Z]/, "Must contain uppercase")
  .regex(/[a-z]/, "Must contain lowercase")
  .regex(/[0-9]/, "Must contain number")
  .regex(/[^A-Za-z0-9]/, "Must contain special character");
6. SSRF の防止
// ❌ SSRF vulnerability
export async function fetchUrl(url: string) {
  return await fetch(url);
}

// ✅ Whitelist approach
const ALLOWED_DOMAINS = ["api.example.com", "data.gov.sg"];

export async function fetchUrl(url: string) {
  const parsedUrl = new URL(url);
  if (!ALLOWED_DOMAINS.includes(parsedUrl.hostname)) {
    throw new Error("Domain not allowed");
  }
  return await fetch(url);
}

入力の検証

import { z } from "zod";

const userInputSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150),
});

export async function createUser(data: unknown) {
  const validated = userInputSchema.parse(data);
  // Now safe to use
}

CORS の設定

// ❌ Too permissive
app.use(cors({ origin: "*" }));

// ✅ Whitelist specific origins
app.use(cors({
  origin: [
    "https://sgcarstrends.com",
    "https://staging.sgcarstrends.com",
    process.env.NODE_ENV === "development" ? "http://localhost:3001" : "",
  ].filter(Boolean),
  credentials: true,
}));

セキュリティヘッダー

// next.config.js
const securityHeaders = [
  { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
  { key: "X-Frame-Options", value: "SAMEORIGIN" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-XSS-Protection", value: "1; mode=block" },
  { key: "Referrer-Policy", value: "origin-when-cross-origin" },
];

module.exports = {
  async headers() {
    return [{ source: "/:path*", headers: securityHeaders }];
  },
};

環境変数

// ❌ Hardcoded secret
const apiKey = "sk_live_EXAMPLE_NOT_REAL";

// ✅ From environment with validation
import { z } from "zod";

const envSchema = z.object({
  API_KEY: z.string().min(1),
  DATABASE_URL: z.string().url(),
});

const env = envSchema.parse(process.env);

CI との統合

# .github/workflows/security.yml
name: Security Audit

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 0 * * 1'  # Weekly

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
      - run: pnpm install
      - run: pnpm audit --audit-level=high

セキュリティチェックリスト

  • すべてのユーザー入力を検証する(Zod スキーマ)
  • SQL インジェクションを防止する(ORM を使用)
  • XSS を防止する(React によるエスケープ、サニタイズ)
  • 認証を正しく実装する
  • 認可チェックを実施する
  • パスワードをハッシュ化する(bcrypt/argon2)
  • レート制限を設定する
  • セキュリティヘッダーを設定する
  • CORS を適切に設定する
  • HTTPS を強制する
  • 依存関係を監査する(pnpm audit)
  • シークレットを環境変数に設定する
  • エラーメッセージから情報が漏えいしないようにする

参考資料

コメント