secure-code-guardian by jeffallan/claude-skills
npx skills add https://github.com/jeffallan/claude-skills --skill secure-code-guardian每个实施步骤后,验证:
' OR 1=1--)被拒绝;确认 XSS 载荷(<script>alert(1)</script>)被转义或拒绝。curl -I、Mozilla Observatory)验证安全头是否存在以及 CORS 源允许列表是否正确。根据上下文加载详细指导:
| 主题 |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 参考 |
|---|
| 加载时机 |
|---|
| OWASP | references/owasp-prevention.md | OWASP Top 10 模式 |
| 身份验证 | references/authentication.md | 密码哈希、JWT |
| 输入验证 | references/input-validation.md | Zod、SQL 注入 |
| XSS/CSRF | references/xss-csrf.md | XSS 防护、CSRF |
| 头部 | references/security-headers.md | Helmet、速率限制 |
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // 最低 10;12 在安全性和性能之间取得平衡
export async function hashPassword(plaintext: string): Promise<string> {
return bcrypt.hash(plaintext, SALT_ROUNDS);
}
export async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {
return bcrypt.compare(plaintext, hash);
}
// 禁止:`SELECT * FROM users WHERE email = '${email}'`
// 始终:使用位置参数
import { Pool } from 'pg';
const pool = new Pool();
export async function getUserByEmail(email: string) {
const { rows } = await pool.query(
'SELECT id, email, role FROM users WHERE email = $1',
[email] // 单独传递值 — 永不插值
);
return rows[0] ?? null;
}
import { z } from 'zod';
const LoginSchema = z.object({
email: z.string().email().max(254),
password: z.string().min(8).max(128),
});
export function validateLoginInput(raw: unknown) {
const result = LoginSchema.safeParse(raw);
if (!result.success) {
// 返回通用错误 — 切勿回显原始输入
throw new Error('Invalid credentials format');
}
return result.data;
}
import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET!; // 切勿硬编码
export function verifyToken(token: string): jwt.JwtPayload {
// 如果过期、被篡改或算法错误则抛出异常
const payload = jwt.verify(token, JWT_SECRET, {
algorithms: ['HS256'], // 显式允许列表算法
issuer: 'your-app',
audience: 'your-app',
});
if (typeof payload === 'string') throw new Error('Invalid token payload');
return payload;
}
import express from 'express';
import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
const app = express();
app.use(helmet()); // 设置 CSP、HSTS、X-Frame-Options 等
app.use(express.json({ limit: '10kb' })); // 限制负载大小
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 分钟
max: 10, // 每个 IP 每个窗口 10 次尝试
standardHeaders: true,
legacyHeaders: false,
});
app.post('/api/login', authLimiter, async (req, res) => {
// 1. 验证输入
const { email, password } = validateLoginInput(req.body);
// 2. 身份验证 — 参数化查询,恒定时间比较
const user = await getUserByEmail(email);
if (!user || !(await verifyPassword(password, user.passwordHash))) {
// 通用消息 — 不透露邮箱是否存在
return res.status(401).json({ error: 'Invalid credentials' });
}
// 3. 授权 — 签发有作用域的、短期有效的令牌
const token = jwt.sign(
{ sub: user.id, role: user.role },
JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '15m', issuer: 'your-app', audience: 'your-app' }
);
// 4. 安全响应 — 令牌在 httpOnly cookie 中,不在响应体中
res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'strict' });
return res.json({ message: 'Authenticated' });
});
实施安全功能时,提供:
OWASP Top 10、bcrypt/argon2、JWT、OAuth 2.0、OIDC、CSP、CORS、速率限制、输入验证、输出编码、加密(AES、RSA)、TLS、安全头
每周安装量
1.0K
仓库
GitHub 星标数
7.3K
首次出现
Jan 20, 2026
安全审计
安装于
opencode845
gemini-cli816
codex793
claude-code777
github-copilot758
cursor743
After each implementation step, verify:
' OR 1=1--) are rejected; confirm XSS payloads (<script>alert(1)</script>) are escaped or rejected.curl -I, Mozilla Observatory) that security headers are present and CORS origin allowlist is correct.Load detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| OWASP | references/owasp-prevention.md | OWASP Top 10 patterns |
| Authentication | references/authentication.md | Password hashing, JWT |
| Input Validation | references/input-validation.md | Zod, SQL injection |
| XSS/CSRF | references/xss-csrf.md | XSS prevention, CSRF |
| Headers | references/security-headers.md |
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // minimum 10; 12 balances security and performance
export async function hashPassword(plaintext: string): Promise<string> {
return bcrypt.hash(plaintext, SALT_ROUNDS);
}
export async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {
return bcrypt.compare(plaintext, hash);
}
// NEVER: `SELECT * FROM users WHERE email = '${email}'`
// ALWAYS: use positional parameters
import { Pool } from 'pg';
const pool = new Pool();
export async function getUserByEmail(email: string) {
const { rows } = await pool.query(
'SELECT id, email, role FROM users WHERE email = $1',
[email] // value passed separately — never interpolated
);
return rows[0] ?? null;
}
import { z } from 'zod';
const LoginSchema = z.object({
email: z.string().email().max(254),
password: z.string().min(8).max(128),
});
export function validateLoginInput(raw: unknown) {
const result = LoginSchema.safeParse(raw);
if (!result.success) {
// Return generic error — never echo raw input back
throw new Error('Invalid credentials format');
}
return result.data;
}
import jwt from 'jsonwebtoken';
const JWT_SECRET = process.env.JWT_SECRET!; // never hardcode
export function verifyToken(token: string): jwt.JwtPayload {
// Throws if expired, tampered, or wrong algorithm
const payload = jwt.verify(token, JWT_SECRET, {
algorithms: ['HS256'], // explicitly allowlist algorithm
issuer: 'your-app',
audience: 'your-app',
});
if (typeof payload === 'string') throw new Error('Invalid token payload');
return payload;
}
import express from 'express';
import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
const app = express();
app.use(helmet()); // sets CSP, HSTS, X-Frame-Options, etc.
app.use(express.json({ limit: '10kb' })); // limit payload size
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // 10 attempts per window per IP
standardHeaders: true,
legacyHeaders: false,
});
app.post('/api/login', authLimiter, async (req, res) => {
// 1. Validate input
const { email, password } = validateLoginInput(req.body);
// 2. Authenticate — parameterized query, constant-time compare
const user = await getUserByEmail(email);
if (!user || !(await verifyPassword(password, user.passwordHash))) {
// Generic message — do not reveal whether email exists
return res.status(401).json({ error: 'Invalid credentials' });
}
// 3. Authorize — issue scoped, short-lived token
const token = jwt.sign(
{ sub: user.id, role: user.role },
JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '15m', issuer: 'your-app', audience: 'your-app' }
);
// 4. Secure response — token in httpOnly cookie, not body
res.cookie('token', token, { httpOnly: true, secure: true, sameSite: 'strict' });
return res.json({ message: 'Authenticated' });
});
When implementing security features, provide:
OWASP Top 10, bcrypt/argon2, JWT, OAuth 2.0, OIDC, CSP, CORS, rate limiting, input validation, output encoding, encryption (AES, RSA), TLS, security headers
Weekly Installs
1.0K
Repository
GitHub Stars
7.3K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode845
gemini-cli816
codex793
claude-code777
github-copilot758
cursor743
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
| Helmet, rate limiting |