安全扫描
wescode 内置安全扫描能力,帮助你在开发阶段发现和修复安全漏洞,遵循安全编码最佳实践。
功能概览
| 能力 | 说明 |
|---|---|
| 漏洞检测 | 检测代码中的安全漏洞和风险 |
| 依赖审计 | 扫描第三方依赖的已知漏洞 |
| 代码审查 | 安全视角的代码 review |
| 最佳实践 | 安全编码最佳实践建议 |
| 合规检查 | 行业安全标准合规检测 |
漏洞检测
自动扫描
在编码过程中,wescode 会自动检测常见的安全漏洞:
AI 实时提醒:
⚠ 安全风险:SQL 注入
文件:internal/repository/user.go:45
代码:db.Raw("SELECT * FROM users WHERE name = '" + name + "'")
→ 使用参数化查询替代字符串拼接
检测范围
| 漏洞类型 | 说明 | 严重级别 |
|---|---|---|
| SQL 注入 | 未参数化的 SQL 查询 | 🔴 严重 |
| XSS | 未转义的用户输入渲染 | 🔴 严重 |
| 命令注入 | 拼接用户输入执行系统命令 | 🔴 严重 |
| 路径遍历 | 未校验的文件路径访问 | 🟠 高 |
| 硬编码凭据 | 代码中的密钥、密码 | 🟠 高 |
| 不安全的随机数 | 使用 math/rand 代替 crypto/rand | 🟡 中 |
| 信息泄露 | 错误信息暴露内部细节 | 🟡 中 |
| SSRF | 未校验的外部 URL 请求 | 🟠 高 |
| 不安全的反序列化 | 反序列化不可信数据 | 🔴 严重 |
| 弱加密 | 使用已知不安全的加密算法 | 🟠 高 |
使用方式
用户:扫描项目的安全漏洞
AI:安全扫描结果:
🔴 严重(2 个):
1. SQL 注入 — internal/repository/user.go:45
db.Raw("SELECT * FROM users WHERE email = '" + email + "'")
修复:
db.Raw("SELECT * FROM users WHERE email = ?", email)
2. 硬编码 JWT 密钥 — internal/auth/jwt.go:12
var jwtSecret = []byte("my-secret-key-123")
修复:
var jwtSecret = []byte(os.Getenv("JWT_SECRET"))
🟠 高(3 个):
3. 路径遍历 — internal/handler/file.go:28
filepath := "/uploads/" + filename
修复:
filepath := filepath.Join("/uploads/", filepath.Base(filename))
4. SSRF — internal/service/webhook.go:55
resp, err := http.Get(userProvidedURL)
修复:
添加 URL 白名单校验和内网地址过滤
5. 弱密码哈希 — internal/auth/password.go:20
md5.Sum([]byte(password))
修复:
bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
🟡 中(4 个):
...
总计:9 个安全问题
→ 是否逐个修复严重和高危问题?
依赖审计
扫描依赖漏洞
用户:检查依赖的安全性
AI:依赖安全审计报告:
扫描范围:go.mod(45 个直接依赖 + 33 个间接依赖)
🔴 严重漏洞(1 个):
┌────────────────────────────────┬──────────┬─────────┐
│ 依赖 │ 当前版本 │ 修复版本 │
├────────────────────────────────┼──────────┼─────────┤
│ golang.org/x/crypto │ v0.14.0 │ v0.21.0 │
│ CVE-2024-xxxxx │ │ │
│ 影响:SSH 密钥交换缓冲区溢出 │ │ │
└────────────────────────────────┴──────────┴─────────┘
🟠 高危漏洞(2 个):
┌────────────────────────────────┬──────────┬─────────┐
│ github.com/gin-gonic/gin │ v1.9.0 │ v1.9.1 │
│ CVE-2024-xxxxx │ │ │
│ 影响:路由参数注入 │ │ │
├────────────────────────────────┼──────────┼─────────┤
│ github.com/go-sql-driver/mysql│ v1.7.0 │ v1.7.1 │
│ CVE-2024-xxxxx │ │ │
│ 影响:特殊字符转义不完整 │ │ │
└────────────────────────────────┴──────────┴─────────┘
⚠ 已弃用依赖(1 个):
- github.com/dgrijalva/jwt-go → 迁移到 github.com/golang-jwt/jwt/v5
✓ 安全依赖:75 个
修复命令:
go get golang.org/x/crypto@v0.21.0
go get github.com/gin-gonic/gin@v1.9.1
go get github.com/go-sql-driver/mysql@v1.7.1
go mod tidy
定期审计
建议将依赖审计纳入 CI 流程:
# .github/workflows/security.yml
- name: 依赖安全扫描
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
代码审查
安全视角的 Review
用户:从安全角度 review 这段认证代码
AI:安全代码审查结果:
文件:internal/auth/login.go
✓ 良好实践:
- 使用 bcrypt 比较密码
- 登录失败有速率限制
- 密码不出现在日志中
⚠ 需要改进:
1. 第 35 行:错误信息泄露
if user == nil {
return nil, errors.New("user not found")
}
if !checkPassword(password, user.PasswordHash) {
return nil, errors.New("wrong password")
}
→ 攻击者可以通过不同的错误信息判断用户名是否存在
→ 修复:统一返回 "invalid credentials"
2. 第 52 行:token 过期时间过长
token, _ := jwt.NewWithClaims(...).SignedString(secret)
// expires in 30 days
→ 建议 access token 15 分钟,refresh token 7 天
3. 第 60 行:未记录登录事件
→ 添加审计日志:记录 IP、User-Agent、登录结果
→ 用于异常登录检测
4. 缺失:
- 没有多因素认证(MFA)选项
- 没有密码复杂度要求
- 没有登录失败锁定机制
敏感数据检查
用户:检查代码中是否有敏感信息泄露
AI:敏感信息扫描结果:
🔴 发现敏感信息(4 处):
1. 硬编码 API Key
文件:internal/service/payment.go:15
const stripeKey = "sk_live_xxxxxxxxxxxxxxxxx"
→ 移到环境变量
2. 测试密码泄露
文件:internal/auth/auth_test.go:30
password := "admin123"
→ 测试中可以接受,但确保不是生产密码
3. 数据库连接字符串
文件:internal/config/config.go:8
const defaultDSN = "postgres://admin:password@localhost/db"
→ 使用环境变量,移除默认密码
4. 私钥文件
文件:certs/server.key
→ 添加到 .gitignore,不要提交到代码仓库
最佳实践
安全编码指南
AI 会在你编码时提供安全最佳实践建议:
输入验证
用户:如何安全地处理用户输入?
AI:输入验证最佳实践:
1. 始终在服务端验证
→ 不要依赖前端验证
2. 使用白名单而非黑名单
✗ if contains(input, "<script>") { reject }
✓ if !matches(input, "^[a-zA-Z0-9_]{3,32}quot;) { reject }
3. 对不同上下文分别转义
→ HTML 输出:html.EscapeString()
→ SQL 查询:参数化查询
→ Shell 命令:不要拼接,使用 exec.Command
4. 限制输入长度和类型
→ 用户名:最长 32 字符,仅字母数字
→ 邮箱:标准 RFC 5322 格式
→ 文件名:过滤路径分隔符
5. 使用验证库
→ Go: go-playground/validator
→ 自定义验证器用于业务规则
认证和授权
AI:认证和授权最佳实践:
认证:
- 密码存储使用 bcrypt(cost >= 12)
- JWT access token 过期时间 <= 15 分钟
- Refresh token 单次使用后轮换
- 支持多因素认证(TOTP)
- 登录失败速率限制(5 次/分钟)
授权:
- 使用 RBAC(基于角色的访问控制)
- 在每个端点显式检查权限
- 不要在前端隐藏作为唯一的授权手段
- 资源访问检查所有者身份
- API Key 分配最小权限
加密和密钥管理
AI:加密最佳实践:
✓ 推荐算法:
- 对称加密:AES-256-GCM
- 哈希:SHA-256 / SHA-3
- 密码哈希:bcrypt / argon2
- 密钥交换:X25519
- 数字签名:Ed25519
✗ 避免使用:
- MD5(碰撞攻击)
- SHA-1(碰撞攻击)
- DES / 3DES(密钥太短)
- RC4(多种已知攻击)
密钥管理:
- 不在代码中硬编码密钥
- 使用环境变量或 Vault
- 密钥定期轮换
- 不同环境使用不同密钥
合规检查
OWASP Top 10 检查
用户:按 OWASP Top 10 检查项目安全
AI:OWASP Top 10 (2021) 合规检查:
A01 - 访问控制失效
✓ 所有端点有认证中间件
⚠ 3 个端点缺少授权检查
A02 - 加密机制失效
✓ HTTPS 强制
✗ 日志中包含未脱敏的邮箱
A03 - 注入
✗ 发现 1 处 SQL 注入风险
✓ 其余查询使用参数化
A04 - 不安全的设计
✓ 密码强度验证
⚠ 缺少速率限制
A05 - 安全配置错误
✓ 生产环境关闭 debug
⚠ CORS 配置过于宽松
A06 - 易受攻击的组件
✗ 2 个依赖有已知漏洞
A07 - 认证和身份识别失效
✓ bcrypt 密码哈希
⚠ 缺少 MFA 支持
A08 - 软件和数据完整性失效
✓ 依赖锁定(go.sum)
A09 - 安全日志和监控不足
⚠ 缺少安全事件审计日志
A10 - 服务端请求伪造
✗ 1 处 SSRF 风险
总评:7/10 通过,3 个需要修复
数据隐私合规
用户:检查 GDPR 合规性
AI:GDPR 合规检查:
数据收集:
✓ 仅收集必要的用户信息
⚠ 缺少隐私政策页面
数据存储:
✓ 敏感数据加密存储
⚠ 用户数据无过期/清理策略
数据访问:
⚠ 缺少用户数据导出功能
⚠ 缺少用户数据删除功能
数据传输:
✓ 使用 HTTPS 传输
✓ API 通信加密
建议:
1. 添加 GET /api/v1/users/me/data — 数据导出
2. 添加 DELETE /api/v1/users/me — 账号注销和数据删除
3. 实现用户数据 30 天保留策略
4. 添加隐私政策和 Cookie 同意
安全修复
自动修复
对于常见的安全问题,AI 可以直接生成修复代码:
用户:修复所有严重安全问题
AI:修复 2 个严重问题:
修复 1/2:SQL 注入
文件:internal/repository/user.go:45
- db.Raw("SELECT * FROM users WHERE email = '" + email + "'")
+ db.Raw("SELECT * FROM users WHERE email = ?", email)
修复 2/2:硬编码密钥
文件:internal/auth/jwt.go:12
- var jwtSecret = []byte("my-secret-key-123")
+ var jwtSecret = []byte(os.Getenv("JWT_SECRET"))
⚠ 额外步骤:
- 确保 JWT_SECRET 环境变量已设置
- 旧的硬编码密钥签发的 token 将失效
- 需要通知用户重新登录
验证:go test ./internal/... ✓ PASS
注意事项
- 安全扫描是辅助工具,不能替代专业的安全审计
- 发现的安全问题应按严重级别优先修复
- 修复安全问题后需要重新运行测试确保功能正常
- 敏感信息(API Key、密码)修复后需要轮换
- 建议将安全扫描集成到 CI/CD 流程中