关于 security-review
面向代码审查的安全技能,帮助识别可利用的漏洞。它要求先追踪输入来源并核查上下文,仅报告有明确攻击者可控输入的高置信度问题。
主要功能
- 01审查代码中的安全漏洞
- 02追踪输入数据流与来源
- 03检查验证和框架防护
- 04按置信度筛选问题
- 05按严重程度组织报告
适用场景
- 01审查 API 路由和端点
- 02检查前端代码与模板
- 03评估文件上传和外部请求
- 04审查 CI/CD 与依赖配置
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ getsentry/ skills --skill security-review安装后在 Claude Code 中输入/security-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSESPEC.mdinfrastructure/docker.mdlanguages/javascript.mdpython.mdreferences/api-security.mdauthentication.mdauthorization.mdbusiness-logic.mdcryptography.mdcsrf.mddata-protection.mddeserialization.mderror-handling.mdfile-security.mdinjection.mdlogging.mdmisconfiguration.mdmodern-threats.mdssrf.mdsupply-chain.mdxss.md详细介绍
安全审查技能
识别代码中可被利用的安全漏洞。只报告高置信度发现——存在明确的漏洞模式,且输入由攻击者控制。
范围:研究与报告
关键区别:
- 报告范围:仅限用户提供的特定文件、差异或代码
- 研究范围:整个代码库,用于在报告前建立信心
标记任何问题前,你必须先研究代码库,了解:
- 此输入实际上来自哪里?(追踪数据流)
- 是否在其他位置进行了验证或清理?
- 此项如何配置?(检查设置、配置文件、中间件)
- 框架提供了哪些保护?
**不要仅凭模式匹配报告问题。**应先调查,再仅报告你确信可被利用的问题。
置信度等级
| 等级 | 标准 | 操作 |
|---|---|---|
| 高 | 已确认存在漏洞模式,且输入由攻击者控制 | 报告并标注严重程度 |
| 中 | 存在漏洞模式,但输入来源不明确 | 标注为“需要验证” |
| 低 | 理论上的问题、最佳实践或纵深防御措施 | 不要报告 |
不要标记的问题
通用规则
- 测试文件(除非明确在审查测试安全性)
- 死代码、注释掉的代码、文档字符串
- 使用常量或服务器控制的配置的模式
- 必须先通过身份验证才能到达的代码路径(请改为注明身份验证要求)
服务器控制的值(非攻击者控制)
这些值由运营人员配置,而非攻击者控制:
| 来源 | 示例 | 安全原因 |
|---|---|---|
| Django 设置 | settings.API_URL、settings.ALLOWED_HOSTS | 在部署时通过配置或环境变量设置 |
| 环境变量 | os.environ.get('DATABASE_URL') | 部署配置 |
| 配置文件 | config.yaml、app.config['KEY'] | 服务器端文件 |
| 框架常量 | django.conf.settings.* | 用户无法修改 |
| 硬编码值 | BASE_URL = "https://api.internal" | 编译时常量 |
SSRF 示例——不是漏洞:
# SAFE: URL comes from Django settings (server-controlled)
response = requests.get(f"{settings.SEER_AUTOFIX_URL}{path}")
SSRF 示例——是漏洞:
# VULNERABLE: URL comes from request (attacker-controlled)
response = requests.get(request.GET.get('url'))
框架缓解的模式
标记问题前,请先查阅语言指南。常见误报:
| 模式 | 通常安全的原因 |
|---|---|
Django {{ variable }} | 默认自动转义 |
React {variable} | 默认自动转义 |
Vue {{ variable }} | 默认自动转义 |
User.objects.filter(id=input) | ORM 会对查询参数化 |
cursor.execute("...%s", (input,)) | 参数化查询 |
innerHTML = "<b>Loading...</b>" | 常量字符串,不含用户输入 |
仅在以下情况标记:
- Django:
{{ var|safe }}、{% autoescape off %}、mark_safe(user_input) - React:
dangerouslySetInnerHTML={{__html: userInput}} - Vue:
v-html="userInput" - ORM:使用字符串插值的
.raw()、.extra()、RawSQL()
审查流程
1. 检测上下文
我正在审查哪类代码?
| 代码类型 | 加载以下参考资料 |
|---|---|
| API 端点、路由 | authorization.md、authentication.md、injection.md |
| Django/DRF 视图、权限类、对象级访问 | 如果有 django-access-review 技能,则使用该技能审查访问控制;否则使用 authorization.md |
| 前端、模板 | xss.md、csrf.md、modern-threats.md(DOM clobbering、原型污染) |
| 文件处理、上传 | file-security.md |
| 加密、机密、令牌 | cryptography.md、data-protection.md |
| 数据序列化 | deserialization.md |
| 外部请求 | ssrf.md |
| 业务工作流 | business-logic.md |
| GraphQL、REST 设计 | api-security.md |
| 配置、标头、CORS | misconfiguration.md |
| CI/CD、依赖项 | supply-chain.md |
| 错误处理 | error-handling.md |
| 审计、日志记录 | logging.md |
对象合并/克隆、__proto__、DOM id/name 查找、WebSocket 处理程序、LLM 提示词构造 | modern-threats.md |
2. 加载语言指南
根据文件扩展名或导入项判断:
| 指示项 | 指南 |
|---|---|
.py、django、flask、fastapi | languages/python.md |
.js、.ts、express、react、vue、next | languages/javascript.md |
其他语言没有专门的指南;请参考 references/ 文件,并直接在代码库中核实框架的防护措施。
3. 加载基础设施指南(如适用)
| 文件类型 | 指南 |
|---|---|
Dockerfile、.dockerignore | infrastructure/docker.md |
| GitHub Actions 工作流 | 如果有 gha-security-review 技能,则使用该技能;否则使用 references/supply-chain.md |
| 其他 CI/CD 流水线、锁文件、包清单 | references/supply-chain.md |
4. 标记问题前先调查
对于每个潜在问题,调查代码库以提高判断把握:
- 此值实际上来自哪里?追踪数据流。
- 它是在部署时配置的(设置、环境变量),还是来自用户输入?
- 其他位置是否进行了验证、清理或允许列表检查?
- 适用哪些框架防护措施?
只有在了解更广泛的上下文后仍有高度把握的问题,才应报告。
5. 验证可利用性
对于每个潜在发现,请确认:
输入是否由攻击者控制?
| 攻击者可控(需调查) | 服务端控制(通常安全) |
|---|---|
request.GET、request.POST、request.args | settings.X、app.config['X'] |
request.json、request.data、request.body | os.environ.get('X') |
request.headers(大多数标头) | 硬编码常量 |
request.cookies(未签名) | 来自配置的内部服务 URL |
URL 路径段:/users/<id>/ | 来自管理员/系统的数据库内容 |
| 文件上传(内容和名称) | 已签名的会话数据 |
| 其他用户提供的数据库内容 | 框架设置 |
| WebSocket 消息 |
框架是否能缓解此问题?
- 查阅语言指南,了解自动转义、参数化处理
- 检查是否有清理数据的中间件/装饰器
上游是否进行了验证?
- 此代码之前的输入验证
- 清理库(DOMPurify、bleach 等)
6. 仅报告高度可信的问题
跳过理论上的问题。只报告经过调查并确认可利用的问题。
严重性分类
| 严重性 | 影响 | 示例 |
|---|---|---|
| 严重 | 可直接利用、影响严重、无需身份验证 | RCE、导致数据泄露的 SQL 注入、身份验证绕过、硬编码机密 |
| 高 | 满足特定条件即可利用、影响重大 | 存储型 XSS、指向元数据的 SSRF、可访问敏感数据的 IDOR |
| 中 | 需要满足特定条件、影响中等 | 反射型 XSS、针对状态变更操作的 CSRF、路径遍历 |
| 低 | 纵深防御、直接影响极小 | 缺少安全标头、错误信息过于详细、非关键场景中使用弱算法 |
快速模式参考
始终标记(严重)
eval(user_input) # Any language
exec(user_input) # Any language
pickle.loads(user_data) # Python
yaml.load(user_data) # Python (not safe_load)
unserialize($user_data) # PHP
deserialize(user_data) # Java ObjectInputStream
shell=True + user_input # Python subprocess
child_process.exec(user) # Node.js
始终标记(高)
innerHTML = userInput # DOM XSS
dangerouslySetInnerHTML={user} # React XSS
v-html="userInput" # Vue XSS
f"SELECT * FROM x WHERE {user}" # SQL injection
`SELECT * FROM x WHERE ${user}` # SQL injection
os.system(f"cmd {user_input}") # Command injection
始终标记(机密)
password = "hardcoded"
api_key = "sk-..."
AWS_SECRET_ACCESS_KEY = "..."
private_key = "-----BEGIN"
先检查上下文(标记前必须调查)
# SSRF - ONLY if URL is from user input, NOT from settings/config
requests.get(request.GET['url']) # FLAG: User-controlled URL
requests.get(settings.API_URL) # SAFE: Server-controlled config
requests.get(f"{settings.BASE}/{x}") # CHECK: Is 'x' user input?
# Path traversal - ONLY if path is from user input
open(request.GET['file']) # FLAG: User-controlled path
open(settings.LOG_PATH) # SAFE: Server-controlled config
open(f"{BASE_DIR}/{filename}") # CHECK: Is 'filename' user input?
# Open redirect - ONLY if URL is from user input
redirect(request.GET['next']) # FLAG: User-controlled redirect
redirect(settings.LOGIN_URL) # SAFE: Server-controlled config
# Weak crypto - ONLY if used for security purposes
hashlib.md5(file_content) # SAFE: File checksums, caching
hashlib.md5(password) # FLAG: Password hashing
random.random() # SAFE: Non-security uses (UI, sampling)
random.random() for token # FLAG: Security tokens need secrets module
输出格式
## Security Review: [File/Component Name]
### Summary
- **Findings**: X (Y Critical, Z High, ...)
- **Risk Level**: Critical/High/Medium/Low
- **Confidence**: High/Mixed
### Findings
#### [VULN-001] [Vulnerability Type] (Severity)
- **Location**: `file.py:123`
- **Confidence**: High
- **Issue**: [What the vulnerability is]
- **Impact**: [What an attacker could do]
- **Evidence**:
```python
[Vulnerable code snippet]
- 修复:[如何修复]
需要验证
[VERIFY-001][潜在问题]
- 位置:
file.py:456 - 问题:[需要验证的内容]
If no vulnerabilities found, state: "No high-confidence vulnerabilities identified."
---
## Reference Files
### Core Vulnerabilities (`references/`)
| File | Covers |
|------|--------|
| `injection.md` | SQL, NoSQL, OS command, LDAP, template injection |
| `xss.md` | Reflected, stored, DOM-based XSS |
| `authorization.md` | Authorization, IDOR, privilege escalation |
| `authentication.md` | Sessions, credentials, password storage |
| `cryptography.md` | Algorithms, key management, randomness |
| `deserialization.md` | Pickle, YAML, Java, PHP deserialization |
| `file-security.md` | Path traversal, uploads, XXE |
| `ssrf.md` | Server-side request forgery |
| `csrf.md` | Cross-site request forgery |
| `data-protection.md` | Secrets exposure, PII, logging |
| `api-security.md` | REST, GraphQL, mass assignment |
| `business-logic.md` | Race conditions, workflow bypass |
| `modern-threats.md` | Prototype pollution, LLM injection, WebSocket |
| `misconfiguration.md` | Headers, CORS, debug mode, defaults |
| `error-handling.md` | Fail-open, information disclosure |
| `supply-chain.md` | Dependencies, build security |
| `logging.md` | Audit failures, log injection |
### Language Guides (`languages/`)
- `python.md` - Django, Flask, FastAPI patterns
- `javascript.md` - Node, Express, React, Vue, Next.js
### Infrastructure (`infrastructure/`)
- `docker.md` - Container security
评论
支持 Markdown