security-reviewer
9
总安装量
6
周安装量
#31977
全站排名
安装命令
npx skills add https://github.com/seikaikyo/dash-skills --skill security-reviewer
Agent 安装分布
amp
6
github-copilot
6
codex
6
kimi-cli
6
gemini-cli
6
opencode
6
Skill 文档
Security Reviewer (å®å ¨å¯©æ¥)
When to Use
å¨ä»¥ä¸æ æ³ä¸»åä½¿ç¨æ¤ Skillï¼
- 實ä½èªèæææ¬åè½
- èçç¨æ¶è¼¸å ¥ææªæ¡ä¸å³
- å»ºç«æ°ç API 端é»
- èçæ©å¯è³æææè
- 坦使¯ä»åè½
- æ´åç¬¬ä¸æ¹ API
- èçéè/交æç¸éç¨å¼ç¢¼
å®å ¨æª¢æ¥æ¸ å® (10 大é¡å¥)
1. æ©å¯è³æç®¡ç (CRITICAL)
// ç¦æ¢: 硬編碼æ©å¯è³æ
const apiKey = "sk-proj-xxxxx" // çµå°ç¦æ¢
const password = "admin123" // çµå°ç¦æ¢
// æ£ç¢º: 使ç¨ç°å¢è®æ¸
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) {
throw new Error('OPENAI_API_KEY æªè¨å®')
}
檢æ¥é ç®:
- ç¡ç¡¬ç·¨ç¢¼ API keysãtokensãå¯ç¢¼
- æææ©å¯è³æä½¿ç¨ç°å¢è®æ¸
-
.env.localå·²å å ¥ .gitignore - Git æ·å²ä¸ç¡æ©å¯è³æ
- çç¢ç°å¢æ©å¯åæ¾æ¼ Vercel/Render
2. è¼¸å ¥é©è
import { z } from 'zod'
const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
age: z.number().int().min(0).max(150)
})
export async function createUser(input: unknown) {
const validated = CreateUserSchema.parse(input)
return await db.users.create(validated)
}
檢æ¥é ç®:
- ææç¨æ¶è¼¸å ¥ä½¿ç¨ Zod é©è
- æªæ¡ä¸å³éå¶ (大å°ãé¡åã坿ªå)
- é¯èª¤è¨æ¯ä¸æ´©é²ææè³è¨
3. SQL æ³¨å ¥é²è· (CRITICAL)
// ç¦æ¢: åä¸²ä¸²æ¥ SQL
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
// æ£ç¢º: åæ¸åæ¥è©¢
const { data } = await supabase
.from('users')
.select('*')
.eq('email', userEmail)
檢æ¥é ç®:
- ææè³æåº«æ¥è©¢ä½¿ç¨åæ¸åæ¥è©¢
- ç¡åä¸²ä¸²æ¥ SQL
- ORM/Query Builder æ£ç¢ºä½¿ç¨
4. èªèèææ¬
// æ£ç¢º: JWT Token ä½¿ç¨ httpOnly cookies
res.setHeader('Set-Cookie',
`token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)
// æ£ç¢º: ææ¬æª¢æ¥
export async function deleteUser(userId: string, requesterId: string) {
const requester = await db.users.findUnique({ where: { id: requesterId } })
if (requester.role !== 'admin') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 403 })
}
await db.users.delete({ where: { id: userId } })
}
檢æ¥é ç®:
- Tokens åæ¾æ¼ httpOnly cookies (é localStorage)
- æææä½åé©èææ¬
- Supabase åç¨ Row Level Security
- å¯¦ä½ RBAC
5. XSS é²è·
import DOMPurify from 'isomorphic-dompurify'
function renderUserContent(html: string) {
const clean = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
ALLOWED_ATTR: []
})
return <div dangerouslySetInnerHTML={{ __html: clean }} />
}
檢æ¥é ç®:
- ç¨æ¶æä¾ç HTML å·²æ¸ ç
- è¨å® CSP æ¨é
- ä½¿ç¨ React å §å»ºç XSS é²è·
6. CSRF é²è·
// SameSite Cookies
res.setHeader('Set-Cookie',
`session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)
檢æ¥é ç®:
- çæ è®æ´æä½ä½¿ç¨ CSRF tokens
- ææ cookies è¨å® SameSite=Strict
7. éçéå¶
import rateLimit from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 åé
max: 100, // æ¯è¦çª 100 è«æ±
message: 'è«æ±éå¤ï¼è«ç¨å¾å試'
})
app.use('/api/', limiter)
檢æ¥é ç®:
- ææ API 端é»åç¨éçéå¶
- æè²´æä½ææ´å´æ ¼çéå¶
8. ææè³æå¤æ´©
// ç¦æ¢: è¨éææè³æ
console.log('User login:', { email, password })
// æ£ç¢º: æ¸
çæ¥èª
console.log('User login:', {
email: email.replace(/(?<=.).(?=.*@)/g, '*'),
passwordProvided: !!password
})
檢æ¥é ç®:
- æ¥èªä¸ç¡å¯ç¢¼ãtokensãæ©å¯è³æ
- é¯èª¤è¨æ¯å°ç¨æ¶æ¯éç¨ç
- 詳細é¯èª¤å å¨ä¼ºæå¨æ¥èª
9. åå¡éå®å ¨ (Solana)
// é©èé¢å
ç°½å
import { verify } from '@solana/web3.js'
async function verifyWalletOwnership(publicKey: string, signature: string, message: string) {
return verify(
Buffer.from(message),
Buffer.from(signature, 'base64'),
Buffer.from(publicKey, 'base64')
)
}
檢æ¥é ç®:
- é¢å ç°½åå·²é©è
- 交æç´°ç¯å·²é©è
- 交æåé¤é¡æª¢æ¥
- ç¡ç²ç°½äº¤æ
10. ä¾è³´å®å ¨
# æª¢æ¥æ¼æ´
npm audit
# èªå修復
npm audit fix
# æ´æ°ä¾è³´
npm update
檢æ¥é ç®:
- ä¾è³´ä¿æææ°
- npm audit ç¡å·²ç¥æ¼æ´
- lock æªæ¡å·²æäº¤
- GitHub Dependabot å·²åç¨
å®å ¨å¯©æ¥å ±åæ ¼å¼
# å®å
¨å¯©æ¥å ±å
**æªæ¡:** [path/to/file.ts]
**å¯©æ¥æ¥æ:** YYYY-MM-DD
**審æ¥è
:** security-reviewer
## æè¦
- **å´éåé¡:** X
- **é«é¢¨éªåé¡:** Y
- **ä¸é¢¨éªåé¡:** Z
- **風éªçç´:** é« / ä¸ / ä½
## å´éåé¡ (ç«å³ä¿®å¾©)
### 1. [å顿¨é¡]
**å´éç¨åº¦:** CRITICAL
**é¡å¥:** SQL 注å
¥ / XSS / èªè / ç
**ä½ç½®:** `file.ts:123`
**åé¡æè¿°:**
[æ¼æ´æè¿°]
**å½±é¿:**
[被å©ç¨æç徿]
**ä¿®å¾©æ¹æ¡:**
[å®å
¨å¯¦ä½ç¯ä¾]
é¨ç½²åå®å ¨æª¢æ¥æ¸ å®
- æ©å¯è³æ: ç¡ç¡¬ç·¨ç¢¼ï¼å ¨é¨ä½¿ç¨ç°å¢è®æ¸
- è¼¸å ¥é©è: ææç¨æ¶è¼¸å ¥å·²é©è
- SQL æ³¨å ¥: æææ¥è©¢å·²åæ¸å
- XSS: ç¨æ¶å §å®¹å·²æ¸ ç
- CSRF: é²è·å·²åç¨
- èªè: æ£ç¢ºç token èç
- ææ¬: è§è²æª¢æ¥å·²å°±ä½
- éçéå¶: ææç«¯é»å·²åç¨
- HTTPS: çç¢ç°å¢å¼·å¶
- å®å ¨æ¨é : CSPãX-Frame-Options å·²è¨å®
- ä¾è³´: ææ°ä¸ç¡æ¼æ´
ç·æ¥æè®
ç¼ç¾ CRITICAL æ¼æ´æï¼
- è¨é – 建ç«è©³ç´°å ±å
- éç¥ – ç«å³è¦åå°æ¡è² 責人
- 建è°ä¿®å¾© – æä¾å®å ¨ç¨å¼ç¢¼ç¯ä¾
- 測試修復 – é©è修復ææ
- è¼ªææ©å¯ – 妿夿´©åæ´æ