owasp-security-check
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOWASP Security Check
OWASP安全检查
Comprehensive security audit patterns for web applications and REST APIs. Contains 20 rules across 5 categories covering OWASP Top 10 and common web vulnerabilities.
针对Web应用和REST API的全面安全审计规范。包含5个类别共20条规则,覆盖OWASP Top 10及常见Web漏洞。
When to Apply
适用场景
Use this skill when:
- Auditing a codebase for security vulnerabilities
- Reviewing user-provided file or folder for security issues
- Checking authentication/authorization implementations
- Evaluating REST API security
- Assessing data protection measures
- Reviewing configuration and deployment settings
- Before production deployment
- After adding new features that handle sensitive data
在以下场景使用本技能:
- 审计代码库以排查安全漏洞
- 评审用户提供的文件或文件夹中的安全问题
- 检查身份验证/授权实现逻辑
- 评估REST API安全性
- 评估数据保护措施
- 评审配置与部署设置
- 生产环境部署前
- 添加处理敏感数据的新功能后
How to Use This Skill
使用方法
- Identify application type - Web app, REST API, SPA, SSR, or mixed
- Scan by priority - Start with CRITICAL rules, then HIGH, then MEDIUM
- Review relevant rule files - Load specific rules from @rules/ directory
- Report findings - Note severity, file location, and impact
- Provide remediation - Give concrete code examples for fixes
- 确定应用类型 - Web应用、REST API、SPA、SSR或混合架构
- 按优先级扫描 - 先检查CRITICAL(严重)规则,再HIGH(高),最后MEDIUM(中)
- 查看相关规则文件 - 从@rules/目录加载特定规则
- 记录发现的问题 - 标注严重程度、文件位置及影响
- 提供修复方案 - 给出具体的代码修复示例
Audit Workflow
审计流程
Step 1: Systematic Review by Priority
步骤1:按优先级系统化评审
Work through categories by priority:
- CRITICAL: Authentication & Authorization, Data Protection, Input/Output Security
- HIGH: Configuration & Headers
- MEDIUM: API & Monitoring
按优先级依次处理各类别:
- CRITICAL(严重):身份验证与授权、数据保护、输入/输出安全
- HIGH(高):配置与安全头
- MEDIUM(中):API与监控
Step 2: Generate Report
步骤2:生成报告
Format findings as:
- Severity: CRITICAL | HIGH | MEDIUM | LOW
- Category: Rule name
- File: Path and line number
- Issue: What's wrong
- Impact: Security consequence
- Fix: Code example of remediation
按以下格式记录发现的问题:
- 严重程度:CRITICAL | HIGH | MEDIUM | LOW
- 类别:规则名称
- 文件:路径及行号
- 问题:具体问题描述
- 影响:安全后果
- 修复方案:代码修复示例
Rules Summary
规则摘要
Authentication & Authorization (CRITICAL)
身份验证与授权(CRITICAL)
broken-access-control - @rules/broken-access-control.md
broken-access-control - @rules/broken-access-control.md
Check for missing authorization, IDOR, privilege escalation.
typescript
// 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));
}检查是否存在缺失授权、IDOR(不安全的直接对象引用)、权限提升问题。
typescript
// 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
authentication-failures - @rules/authentication-failures.md
Check for weak authentication, missing MFA, session issues.
typescript
// 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;
}检查是否存在弱身份验证、缺失MFA(多因素认证)、会话管理问题。
typescript
// 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;
}Data Protection (CRITICAL)
数据保护(CRITICAL)
cryptographic-failures - @rules/cryptographic-failures.md
cryptographic-failures - @rules/cryptographic-failures.md
Check for weak encryption, plaintext storage, bad hashing.
typescript
// Bad: MD5 for passwords
let hash = crypto.createHash("md5").update(password).digest("hex");
// Good: bcrypt with salt
let hash = await bcrypt(password, 12);检查是否存在弱加密、明文存储、哈希算法不当问题。
typescript
// 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
sensitive-data-exposure - @rules/sensitive-data-exposure.md
Check for PII in logs/responses, error messages leaking info.
typescript
// 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,
}),
);检查日志/响应中是否存在PII(个人可识别信息)、错误信息泄露敏感数据问题。
typescript
// 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
data-integrity-failures - @rules/data-integrity-failures.md
Check for unsigned data, insecure deserialization.
typescript
// 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);检查是否存在未签名数据、不安全反序列化问题。
typescript
// 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
secrets-management - @rules/secrets-management.md
Check for hardcoded secrets, exposed env vars.
typescript
// 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");检查是否存在硬编码密钥、环境变量泄露问题。
typescript
// 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");Input/Output Security (CRITICAL)
输入/输出安全(CRITICAL)
injection-attacks - @rules/injection-attacks.md
injection-attacks - @rules/injection-attacks.md
Check for SQL, XSS, NoSQL, Command, Path Traversal injection.
typescript
// Bad: SQL injection
let query = `SELECT * FROM users WHERE email = '${email}'`;
// Good: Parameterized query
let user = await db.user.findUnique({ where: { email } });检查是否存在SQL、XSS、NoSQL、命令注入、路径遍历注入问题。
typescript
// 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
ssrf-attacks - @rules/ssrf-attacks.md
Check for unvalidated URLs, internal network access.
typescript
// 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 });
}检查是否存在未验证URL、内部网络访问问题。
typescript
// 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
file-upload-security - @rules/file-upload-security.md
Check for unrestricted uploads, MIME validation.
typescript
// 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 });
}检查是否存在无限制文件上传、MIME类型验证缺失问题。
typescript
// 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
redirect-validation - @rules/redirect-validation.md
Check for open redirects, unvalidated redirect URLs.
typescript
// 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("/");
}检查是否存在开放重定向、未验证重定向URL问题。
typescript
// 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("/");
}Configuration & Headers (HIGH)
配置与安全头(HIGH)
insecure-design - @rules/insecure-design.md
insecure-design - @rules/insecure-design.md
Check for security anti-patterns in architecture.
typescript
// 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");检查架构中是否存在安全反模式。
typescript
// 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
security-misconfiguration - @rules/security-misconfiguration.md
Check for default configs, debug mode, error handling.
typescript
// 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 });
}检查是否存在默认配置、调试模式开启、错误处理不当问题。
typescript
// 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
security-headers - @rules/security-headers.md
Check for CSP, HSTS, X-Frame-Options, etc.
typescript
// 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",
},
});检查是否存在CSP、HSTS、X-Frame-Options等安全头缺失问题。
typescript
// 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-configuration - @rules/cors-configuration.md
Check for overly permissive CORS.
typescript
// 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);
}检查是否存在过于宽松的CORS配置问题。
typescript
// 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-protection - @rules/csrf-protection.md
Check for CSRF tokens, SameSite cookies.
typescript
// 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",
},
});检查是否存在CSRF令牌缺失、SameSite Cookie未设置问题。
typescript
// 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
session-security - @rules/session-security.md
Check for cookie flags, JWT issues, token storage.
typescript
// 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",
},
});检查是否存在Cookie标志缺失、JWT问题、令牌存储不当问题。
typescript
// 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 & Monitoring (MEDIUM-HIGH)
API与监控(MEDIUM-HIGH)
api-security - @rules/api-security.md
api-security - @rules/api-security.md
Check for REST API vulnerabilities, mass assignment.
typescript
// 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
});检查是否存在REST API漏洞、批量赋值问题。
typescript
// 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
rate-limiting - @rules/rate-limiting.md
Check for missing rate limits, brute force prevention.
typescript
// 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 });
}检查是否存在速率限制缺失、暴力破解防护缺失问题。
typescript
// 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
logging-monitoring - @rules/logging-monitoring.md
Check for insufficient logging, sensitive data in logs.
typescript
// 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(),
});检查是否存在日志记录不足、日志中包含敏感数据问题。
typescript
// 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
vulnerable-dependencies - @rules/vulnerable-dependencies.md
Check for outdated packages, known CVEs.
bash
undefined检查是否存在过期包、已知CVE漏洞问题。
bash
undefinedBad: No dependency checking
Bad: No dependency checking
npm install
npm install
Good: Regular audits
Good: Regular audits
npm audit
npm audit fix
undefinednpm audit
npm audit fix
undefinedCommon Vulnerability Patterns
常见漏洞模式
Quick reference of patterns to look for:
- User input without validation: → immediate use
req.json() - Missing auth checks: Routes without authorization middleware
- Hardcoded secrets: Strings containing "password", "secret", "key"
- SQL injection: String concatenation in queries
- XSS: ,
dangerouslySetInnerHTML.innerHTML - Weak crypto: ,
md5for passwordssha1 - Missing headers: No CSP, HSTS, or security headers
- CORS wildcards: with credentials
Access-Control-Allow-Origin: * - Insecure cookies: Missing Secure, HttpOnly, SameSite flags
- Path traversal: User input in file paths without validation
需重点排查的模式速查:
- 未验证的用户输入:→ 直接使用
req.json() - 缺失权限检查:路由未配置授权中间件
- 硬编码密钥:包含“password”、“secret”、“key”的字符串
- SQL注入:查询中使用字符串拼接
- XSS:、
dangerouslySetInnerHTML.innerHTML - 弱加密:使用、
md5存储密码sha1 - 缺失安全头:未设置CSP、HSTS或其他安全头
- CORS通配符:同时允许凭证
Access-Control-Allow-Origin: * - 不安全Cookie:缺失Secure、HttpOnly、SameSite标志
- 路径遍历:文件路径中使用用户输入且未验证
Severity Quick Reference
严重程度速查
Fix Immediately (CRITICAL):
- SQL/XSS/Command Injection
- Missing authentication on sensitive endpoints
- Hardcoded secrets in code
- Plaintext password storage
- IDOR vulnerabilities
Fix Soon (HIGH):
- Missing CSRF protection
- Weak password requirements
- Missing security headers
- Overly permissive CORS
- Insecure session management
Fix When Possible (MEDIUM):
- Missing rate limiting
- Incomplete logging
- Outdated dependencies (no known exploits)
- Missing input validation on non-critical fields
Improve (LOW):
- Missing optional security headers
- Verbose error messages (non-production)
- Suboptimal crypto parameters
立即修复(CRITICAL):
- SQL/XSS/命令注入
- 敏感端点缺失身份验证
- 代码中硬编码密钥
- 明文存储密码
- IDOR漏洞
尽快修复(HIGH):
- 缺失CSRF防护
- 弱密码要求
- 缺失安全头
- 过于宽松的CORS配置
- 不安全的会话管理
适时修复(MEDIUM):
- 缺失速率限制
- 日志记录不完整
- 过期依赖(无已知漏洞)
- 非敏感字段缺失输入验证
优化项(LOW):
- 缺失可选安全头
- 详细错误信息(非生产环境)
- 非最优加密参数