mcpField
S
security

security

github.com/motormetrics安全2257 次安装今天更新
代码仓库

关于 security

security 是面向应用代码和依赖项安全审查的开发技能,结合审计命令、示例与清单,涵盖常见 Web 风险。

主要功能

  1. 01使用 pnpm audit 和 Snyk 检查
  2. 02OWASP Top 10 审查指导
  3. 03使用 Zod 校验输入
  4. 04访问控制与注入防护示例
  5. 05CORS 和安全标头指导
  6. 06代码及 CI 安全检查清单

适用场景

  1. 01检查依赖项中的已知漏洞
  2. 02审查授权和输入处理
  3. 03加强 CORS 与响应标头
  4. 04在 CI 中加入安全检查

安装

复制下面的命令,在终端中运行。

$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)
  • 密钥已存储在环境变量中
  • 错误消息不会泄露信息

参考资料

评论

支持 Markdown