关于 owasp-security-check
OWASP Security Check 是面向开发者的安全审计技能,用于检查 Web 应用和 REST API。其规则涵盖常见漏洞类别,并提供按严重程度审查、报告发现及给出修复建议的流程。
主要功能
- 01五类共 20 条规则
- 02按严重程度排序的审计流程
- 03检查身份验证与访问控制
- 04覆盖输入、API 和配置风险
- 05报告问题影响并提供修复示例
适用场景
- 01上线前审查 Web 应用
- 02评估身份验证与授权代码
- 03检查 REST API 安全性
- 04检查涉及敏感数据的功能变更
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sergiodxa/ agent-skills --skill owasp-security-check安装后在 Claude Code 中输入/owasp-security-check确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
rules/api-security.mdauthentication-failures.mdbroken-access-control.mdcors-configuration.mdcryptographic-failures.mdcsrf-protection.mddata-integrity-failures.mdfile-upload-security.mdinjection-attacks.mdinsecure-design.mdlogging-monitoring.mdrate-limiting.mdredirect-validation.mdsecrets-management.mdsecurity-headers.mdsecurity-misconfiguration.mdsensitive-data-exposure.mdsession-security.mdssrf-attacks.mdvulnerable-dependencies.md详细介绍
OWASP 安全检查
面向 Web 应用和 REST API 的全面安全审计模式。包含 5 个类别中的 20 条规则,涵盖 OWASP Top 10 和常见 Web 漏洞。
适用场景
在以下情况下使用此技能:
- 审计代码库中的安全漏洞
- 检查用户提供的文件或文件夹是否存在安全问题
- 检查身份验证/授权实现
- 评估 REST API 安全性
- 评估数据保护措施
- 检查配置和部署设置
- 生产环境部署之前
- 添加处理敏感数据的新功能之后
使用此技能的方法
- 识别应用类型——Web 应用、REST API、SPA、SSR 或混合类型
- 按优先级扫描——从 CRITICAL 规则开始,然后检查 HIGH,最后检查 MEDIUM
- 查看相关规则文件——从 @rules/ 目录加载特定规则
- 报告发现的问题——注明严重性、文件位置和影响
- 提供修复方案——给出具体的修复代码示例
审计工作流
步骤 1:按优先级系统化检查
按优先级检查各类别:
- CRITICAL:身份验证与授权、数据保护、输入/输出安全
- HIGH:配置与标头
- MEDIUM:API 与监控
步骤 2:生成报告
按以下格式记录发现的问题:
- Severity:CRITICAL | HIGH | MEDIUM | LOW
- Category:规则名称
- File:路径和行号
- Issue:问题所在
- Impact:安全影响
- Fix:修复方案的代码示例
规则摘要
身份验证与授权(CRITICAL)
broken-access-control - @rules/broken-access-control.md
检查是否缺少授权、存在 IDOR 或权限提升问题。
// Bad: No authorization check
async function getUser(req: Request): Promise<Response> {
let url = new URL(req.url);
let userId = url.searchParams.get("id");
let user = await db.user.findUnique({ where: { id: userId } });
return new Response(JSON.stringify(user));
}
// Good: Verify ownership
async function getUser(req: Request): Promise<Response> {
let session = await getSession(req);
let url = new URL(req.url);
let userId = url.searchParams.get("id");
if (session.userId !== userId && !session.isAdmin) {
return new Response("Forbidden", { status: 403 });
}
let user = await db.user.findUnique({ where: { id: userId } });
return new Response(JSON.stringify(user));
}
authentication-failures - @rules/authentication-failures.md
检查身份验证是否薄弱、是否缺少 MFA,以及会话是否存在问题。
// Bad: Weak password check
if (password.length >= 6) {
/* allow */
}
// Good: Strong password requirements
function validatePassword(password: string) {
if (password.length < 12) return false;
if (!/[A-Z]/.test(password)) return false;
if (!/[a-z]/.test(password)) return false;
if (!/[0-9]/.test(password)) return false;
if (!/[^A-Za-z0-9]/.test(password)) return false;
return true;
}
数据保护(CRITICAL)
cryptographic-failures - @rules/cryptographic-failures.md
检查加密是否薄弱、是否以明文存储,以及哈希处理是否不当。
// Bad: MD5 for passwords
let hash = crypto.createHash("md5").update(password).digest("hex");
// Good: bcrypt with salt
let hash = await bcrypt(password, 12);
sensitive-data-exposure - @rules/sensitive-data-exposure.md
检查日志/响应中是否包含 PII,以及错误消息是否泄露信息。
// Bad: Exposing sensitive data
return new Response(JSON.stringify(user)); // Contains password hash, email, etc.
// Good: Return only needed fields
return new Response(
JSON.stringify({
id: user.id,
username: user.username,
displayName: user.displayName,
}),
);
data-integrity-failures - @rules/data-integrity-failures.md
检查是否存在未经签名的数据和不安全的反序列化。
// Bad: Trusting unsigned JWT
let decoded = JSON.parse(atob(token.split(".")[1]));
if (decoded.isAdmin) {
/* grant access */
}
// Good: Verify signature
let payload = await verifyJWT(token, secret);
secrets-management - @rules/secrets-management.md
检查是否硬编码机密,以及环境变量是否暴露。
// Bad: Hardcoded secret
const API_KEY = "sk_live_a1b2c3d4e5f6";
// Good: Environment variables
let API_KEY = process.env.API_KEY;
if (!API_KEY) throw new Error("API_KEY not configured");
输入/输出安全(CRITICAL)
injection-attacks - @rules/injection-attacks.md
检查是否存在 SQL、XSS、NoSQL、命令注入和路径遍历注入。
// Bad: SQL injection
let query = `SELECT * FROM users WHERE email = '${email}'`;
// Good: Parameterized query
let user = await db.user.findUnique({ where: { email } });
ssrf-attacks - @rules/ssrf-attacks.md
检查 URL 是否经过验证,以及是否能访问内部网络。
// Bad: Fetching user-provided URL
let url = await req.json().then((d) => d.url);
let response = await fetch(url);
// Good: Validate against allowlist
const ALLOWED_DOMAINS = ["api.example.com", "cdn.example.com"];
let url = new URL(await req.json().then((d) => d.url));
if (!ALLOWED_DOMAINS.includes(url.hostname)) {
return new Response("Invalid URL", { status: 400 });
}
file-upload-security - @rules/file-upload-security.md
检查上传是否不受限制,以及是否验证 MIME 类型。
// Bad: No file type validation
let file = await req.formData().then((fd) => fd.get("file"));
await writeFile(`./uploads/${file.name}`, file);
// Good: Validate type and extension
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"];
const ALLOWED_EXTS = [".jpg", ".jpeg", ".png", ".webp"];
let file = await req.formData().then((fd) => fd.get("file") as File);
if (!ALLOWED_TYPES.includes(file.type)) {
return new Response("Invalid file type", { status: 400 });
}
redirect-validation - @rules/redirect-validation.md
检查是否存在开放重定向,以及重定向 URL 是否经过验证。
// Bad: Unvalidated redirect
let returnUrl = new URL(req.url).searchParams.get("return");
return Response.redirect(returnUrl);
// Good: Validate redirect URL
let returnUrl = new URL(req.url).searchParams.get("return");
let allowed = ["/dashboard", "/profile", "/settings"];
if (!allowed.includes(returnUrl)) {
return Response.redirect("/");
}
配置与标头(HIGH)
insecure-design - @rules/insecure-design.md
检查架构中是否存在安全反模式。
// Bad: Security by obscurity
let isAdmin = req.headers.get("x-admin-secret") === "admin123";
// Good: Proper role-based access control
let session = await getSession(req);
let isAdmin = await db.user
.findUnique({
where: { id: session.userId },
})
.then((u) => u.role === "ADMIN");
security-misconfiguration - @rules/security-misconfiguration.md
检查是否存在默认配置、调试模式和错误处理问题。
// Bad: Exposing stack traces
catch (error) {
return new Response(error.stack, { status: 500 });
}
// Good: Generic error message
catch (error) {
console.error(error); // Log server-side only
return new Response("Internal server error", { status: 500 });
}
security-headers - @rules/security-headers.md
检查 CSP、HSTS、X-Frame-Options 等安全标头。
// Bad: No security headers
return new Response(html);
// Good: Security headers set
return new Response(html, {
headers: {
"Content-Security-Policy": "default-src 'self'",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
},
});
cors-configuration - @rules/cors-configuration.md
检查 CORS 配置是否过于宽松。
// Bad: Wildcard with credentials
headers.set("Access-Control-Allow-Origin", "*");
headers.set("Access-Control-Allow-Credentials", "true");
// Good: Specific origin
let allowedOrigins = ["https://app.example.com"];
let origin = req.headers.get("origin");
if (origin && allowedOrigins.includes(origin)) {
headers.set("Access-Control-Allow-Origin", origin);
}
csrf-protection - @rules/csrf-protection.md
检查 CSRF 令牌和 SameSite Cookie。
// Bad: No CSRF protection
let cookies = parseCookies(req.headers.get("cookie"));
let session = await getSession(cookies.sessionId);
// Good: SameSite cookie + token validation
return new Response("OK", {
headers: {
"Set-Cookie": "session=abc; SameSite=Strict; Secure; HttpOnly",
},
});
session-security - @rules/session-security.md
检查 Cookie 标志、JWT 问题和令牌存储。
// Bad: Insecure cookie
return new Response("OK", {
headers: { "Set-Cookie": "session=abc123" },
});
// Good: Secure cookie with all flags
return new Response("OK", {
headers: {
"Set-Cookie":
"session=abc123; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600",
},
});
API 与监控(MEDIUM-HIGH)
api-security - @rules/api-security.md
检查 REST API 漏洞和批量赋值问题。
// Bad: Mass assignment vulnerability
let userData = await req.json();
await db.user.update({ where: { id }, data: userData });
// Good: Explicitly allow fields
let { displayName, bio } = await req.json();
await db.user.update({
where: { id },
data: { displayName, bio }, // Only allowed fields
});
rate-limiting - @rules/rate-limiting.md
检查是否缺少速率限制和暴力破解防护。
// Bad: No rate limiting
async function login(req: Request): Promise<Response> {
let { email, password } = await req.json();
// Allows unlimited login attempts
}
// Good: Rate limiting
let ip = req.headers.get("x-forwarded-for");
let { success } = await ratelimit.limit(ip);
if (!success) {
return new Response("Too many requests", { status: 429 });
}
logging-monitoring - @rules/logging-monitoring.md
检查日志记录是否不足,以及日志中是否包含敏感数据。
// Bad: Logging sensitive data
console.log("User login:", { email, password, ssn });
// Good: Log events without sensitive data
console.log("User login attempt", {
email,
ip: req.headers.get("x-forwarded-for"),
timestamp: new Date().toISOString(),
});
vulnerable-dependencies - @rules/vulnerable-dependencies.md
检查过时的软件包和已知 CVE。
# Bad: No dependency checking
npm install
# Good: Regular audits
npm audit
npm audit fix
常见漏洞模式
以下是需要检查的模式的快速参考:
- 未经验证的用户输入:
req.json()→ 立即使用 - 缺少身份验证检查:未使用授权中间件的路由
- 硬编码密钥:包含 "password"、"secret"、"key" 的字符串
- SQL 注入:在查询中拼接字符串
- XSS:
dangerouslySetInnerHTML、.innerHTML - 弱加密算法:使用
md5、sha1加密密码 - 缺少安全标头:没有 CSP、HSTS 或安全标头
- CORS 通配符:在带凭据的情况下使用
Access-Control-Allow-Origin: * - 不安全的 Cookie:缺少 Secure、HttpOnly、SameSite 标志
- 路径遍历:未验证就将用户输入用于文件路径
严重性快速参考
立即修复(CRITICAL):
- SQL/XSS/命令注入
- 敏感端点缺少身份验证
- 代码中存在硬编码密钥
- 以明文存储密码
- IDOR 漏洞
尽快修复(HIGH):
- 缺少 CSRF 防护
- 密码要求过弱
- 缺少安全标头
- CORS 权限过于宽松
- 会话管理不安全
条件允许时修复(MEDIUM):
- 缺少速率限制
- 日志记录不完整
- 依赖项过时(没有已知漏洞利用)
- 非关键字段缺少输入验证
改进(LOW):
- 缺少可选安全标头
- 错误消息过于详细(非生产环境)
- 加密参数不理想