gitlink-cli/skills/gitlink-code-review/references/code-review-security.md

13 KiB
Raw Blame History

安全性检查

本文档详细说明如何使用 AI 分析代码安全问题。

📋 概述

安全性检查是智能代码审查的关键维度,通过识别常见的安全漏洞和风险,帮助开发者提升代码安全性,防止潜在的安全攻击。

🎯 检查维度

1. SQL 注入SQL Injection

风险等级: 🔴 HIGH

描述: 攻击者通过恶意构造的输入篡改数据库查询逻辑。

检测模式:

  • 字符串拼接 SQL 语句
  • 直接使用用户输入构造查询
  • 未使用参数化查询

示例:

// ❌ 存在 SQL 注入风险
query := "SELECT * FROM users WHERE username = '" + username + "'"
db.Query(query)

// ✅ 安全的参数化查询
query := "SELECT * FROM users WHERE username = ?"
db.Query(query, username)

修复建议:

  1. 使用参数化查询或 ORM
  2. 对用户输入进行验证和转义
  3. 使用最小权限的数据库账户

2. XSS 跨站脚本Cross-Site Scripting

风险等级: 🔴 HIGH

描述: 攻击者在网页中注入恶意脚本,窃取用户信息或进行攻击。

检测模式:

  • 直接输出用户输入到 HTML
  • 未对用户输入进行 HTML 转义
  • 使用 innerHTML 直接插入用户内容

示例:

// ❌ 存在 XSS 风险
div.innerHTML = userComment;
document.write(userName);

// ✅ 安全的 HTML 转义
div.textContent = userComment;
div.innerHTML = escapeHtml(userComment);

function escapeHtml(text) {
    return text
        .replace(/&/g, "&")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
}

修复建议:

  1. 对用户输入进行 HTML 转义
  2. 使用 textContent 而非 innerHTML
  3. 使用 CSPContent Security Policy
  4. 对输出进行白名单验证

3. 敏感信息泄露Sensitive Data Exposure

风险等级: 🔴 HIGH

描述: 代码中包含硬编码的密钥、密码、Token 等敏感信息。

检测模式:

  • 硬编码的密码、密钥、Token
  • 代码中包含 API 密钥
  • 敏感配置信息

示例:

// ❌ 硬编码敏感信息
const (
    DB_PASSWORD = "admin123"
    API_KEY     = "sk-1234567890abcdef"
    SECRET_KEY  = "my-secret-key"
)

// ✅ 使用环境变量
dbPassword := os.Getenv("DB_PASSWORD")
apiKey := os.Getenv("API_KEY")
secretKey := os.Getenv("SECRET_KEY")

修复建议:

  1. 使用环境变量存储敏感信息
  2. 使用配置管理工具(如 Vault
  3. 不要在代码中硬编码密钥
  4. 使用 .env 文件并加入 .gitignore

4. 认证和授权问题Authentication & Authorization

风险等级: 🔴 HIGH

描述: 认证或授权机制存在缺陷,导致未授权访问。

检测模式:

  • 缺少认证检查
  • 权限验证不充分
  • 会话管理不当

示例:

// ❌ 缺少权限检查
func getUserProfile(userID int) (*User, error) {
    return db.GetUser(userID)
}

// ✅ 添加权限检查
func getUserProfile(userID int, currentUser *User) (*User, error) {
    // 检查是否有权限访问该用户信息
    if currentUser.ID != userID && !currentUser.IsAdmin {
        return nil, ErrPermissionDenied
    }
    return db.GetUser(userID)
}

修复建议:

  1. 每个敏感操作都要进行权限检查
  2. 使用最小权限原则
  3. 实施适当的会话管理
  4. 定期轮换密钥和证书

5. 输入验证Input Validation

风险等级: ⚠️ MEDIUM

描述: 对用户输入缺少充分的验证,可能导致各种安全问题。

检测模式:

  • 缺少输入长度检查
  • 缺少输入格式验证
  • 缺少类型检查

示例:

// ❌ 缺少输入验证
function createUser(username, password) {
    db.insert({ username, password });
}

// ✅ 添加输入验证
function createUser(username, password) {
    if (!username || username.length < 3 || username.length > 20) {
        throw new Error('用户名长度必须在 3-20 个字符之间');
    }

    if (!/^[a-zA-Z0-9_]+$/.test(username)) {
        throw new Error('用户名只能包含字母、数字和下划线');
    }

    if (!password || password.length < 8) {
        throw new Error('密码长度至少为 8 个字符');
    }

    db.insert({ username, password });
}

修复建议:

  1. 验证输入长度、格式、类型
  2. 使用白名单而非黑名单
  3. 在客户端和服务端都进行验证
  4. 对不同来源的输入都要验证

6. 资源泄漏Resource Leak

风险等级: ⚠️ MEDIUM

描述: 资源(文件、连接、内存)未正确释放,可能导致 DoS。

检测模式:

  • 文件打开后未关闭
  • 数据库连接未关闭
  • 网络连接未关闭

示例:

// ❌ 资源未关闭
func processData(filename string) error {
    file, _ := os.Open(filename)
    // 处理文件
    // 忘记关闭文件

    db, _ := sql.Open("mysql", dsn)
    // 处理数据库
    // 忘记关闭连接
}

// ✅ 使用 defer 确保资源关闭
func processData(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    db, err := sql.Open("mysql", dsn)
    if err != nil {
        return err
    }
    defer db.Close()

    // 处理文件和数据库
    return nil
}

修复建议:

  1. 使用 defer 确保资源释放
  2. 使用 try-with-resourcesJava
  3. 使用连接池管理数据库连接
  4. 定期检查和清理资源

7. 不安全的随机数Insecure Randomness

风险等级: ⚠️ MEDIUM

描述: 使用可预测的随机数生成器,可能被攻击者预测。

检测模式:

  • 使用 Math.random() 生成安全相关随机数
  • 使用时间戳作为随机种子
  • 使用线性同余生成器

示例:

// ❌ 不安全的随机数
const token = Math.random().toString(36);
const seed = Date.now();
const random = srand(seed);

// ✅ 安全的随机数
const crypto = require('crypto');
const token = crypto.randomBytes(16).toString('hex');

修复建议:

  1. 使用加密安全的随机数生成器
  2. 不要使用时间戳作为随机种子
  3. 对于密钥、Token 等安全相关数据,使用 CSPRNG

8. 不安全的反序列化Insecure Deserialization

风险等级: 🔴 HIGH

描述: 反序列化不受信任的数据可能导致远程代码执行。

检测模式:

  • 反序列化用户输入
  • 使用不安全的序列化格式
  • 缺少完整性验证

示例:

// ❌ 不安全的反序列化
Object obj = deserializeObject(userInput);

// ✅ 安全的反序列化
// 1. 使用白名单限制可反序列化的类型
// 2. 验证数据的完整性
// 3. 使用安全的序列化格式(如 JSON

修复建议:

  1. 避免反序列化不受信任的数据
  2. 使用白名单限制可反序列化的类型
  3. 使用安全的序列化格式(如 JSON
  4. 验证数据的完整性和来源

🔧 分析流程

开始安全性分析
  ↓
1. 解析代码结构
  ├─ 识别数据库操作
  ├─ 识别用户输入处理
  └─ 识别敏感信息
  ↓
2. 检测安全漏洞
  ├─ SQL 注入
  ├─ XSS 跨站脚本
  ├─ 敏感信息泄露
  ├─ 认证授权问题
  ├─ 输入验证
  ├─ 资源泄漏
  ├─ 不安全的随机数
  └─ 不安全的反序列化
  ↓
3. 评估风险等级
  ├─ 根据漏洞类型评估
  ├─ 根据上下文评估
  └─ 根据影响范围评估
  ↓
4. 生成安全报告
  ├─ 漏洞列表
  ├─ 风险等级
  └─ 修复建议
  ↓
完成

📊 输出格式

JSON 格式

{
  "security_analysis": {
    "overall_score": 70,
    "status": "NEEDS_REVIEW",
    "vulnerabilities": [
      {
        "id": 1,
        "severity": "HIGH",
        "category": "sql_injection",
        "title": "SQL 注入漏洞",
        "file": "src/auth/login.go",
        "line": 45,
        "code_snippet": "query := \"SELECT * FROM users WHERE username = '\" + username + \"'\"",
        "description": "直接拼接用户输入到 SQL 语句,存在 SQL 注入风险",
        "impact": "攻击者可以通过构造恶意输入访问或篡改数据库",
        "recommendation": "使用参数化查询或 ORM",
        "references": [
          "https://owasp.org/www-community/attacks/SQL_Injection",
          "https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
        ]
      },
      {
        "id": 2,
        "severity": "HIGH",
        "category": "sensitive_data",
        "title": "敏感信息泄露",
        "file": "config/database.go",
        "line": 10,
        "code_snippet": "const DB_PASSWORD = \"admin123\"",
        "description": "代码中硬编码数据库密码",
        "impact": "敏感信息可能被泄露,导致数据库被攻击",
        "recommendation": "使用环境变量或配置管理工具存储敏感信息",
        "references": [
          "https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html"
        ]
      }
    ],
    "summary": {
      "total": 5,
      "critical": 0,
      "high": 2,
      "medium": 3,
      "low": 0
    }
  }
}

Markdown 格式

## 安全性分析: 70/100 ⚠️

### 🔴 高危漏洞2

#### 1. SQL 注入漏洞
- **文件**: `src/auth/login.go:45`
- **风险等级**: 🔴 HIGH
- **类别**: sql_injection
- **代码**:
  ```go
  query := "SELECT * FROM users WHERE username = '" + username + "'"

2. 敏感信息泄露

  • 文件: config/database.go:10
  • 风险等级: 🔴 HIGH
  • 类别: sensitive_data
  • 代码:
    const DB_PASSWORD = "admin123"
    
  • 描述: 代码中硬编码数据库密码
  • 影响: 敏感信息可能被泄露,导致数据库被攻击
  • 修复建议: 使用环境变量或配置管理工具存储敏感信息

⚠️ 中危漏洞3

1. 输入验证缺失

  • 文件: src/api/user.go:78
  • 风险等级: ⚠️ MEDIUM
  • 修复建议: 添加用户名和密码的格式验证

📊 漏洞统计

  • 总计: 5 个漏洞
  • 🔴 高危: 2 个
  • ⚠️ 中危: 3 个
  • 低危: 0 个

📝 安全建议

  1. 立即修复:修复所有高危漏洞,特别是 SQL 注入和敏感信息泄露
  2. 加强验证:对所有用户输入进行严格的格式和长度验证
  3. 使用工具:集成静态安全分析工具(如 SonarQube、Snyk
  4. 定期审计:定期进行安全代码审查

📚 参考资源


## 💡 最佳实践

### 1. 防御 SQL 注入

```go
// ✅ 使用参数化查询
stmt, err := db.Prepare("SELECT * FROM users WHERE username = ?")
if err != nil {
    return err
}
defer stmt.Close()

rows, err := stmt.Query(username)
if err != nil {
    return err
}
defer rows.Close()

// ✅ 使用 ORM
var user User
result := db.Where("username = ?", username).First(&user)

2. 防御 XSS 攻击

// ✅ 使用 DOMPurify 库
import DOMPurify from 'dompurify';

const clean = DOMPurify.sanitize(userInput);
div.innerHTML = clean;

// ✅ 使用 CSP
// 在 HTML 头中添加 CSP
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

3. 保护敏感信息

// ✅ 使用环境变量
dbPassword := os.Getenv("DB_PASSWORD")

// ✅ 使用配置文件(加密)
config := loadConfig("config.enc")

// ✅ 使用密钥管理服务
secret := vault.GetSecret("database_password")

🔍 常见问题

Q: 如何确定漏洞的风险等级?

A: 综合考虑以下因素:

  • 利用难度: 容易利用的漏洞风险更高
  • 影响范围: 影响范围大的漏洞风险更高
  • 数据敏感性: 涉及敏感数据的漏洞风险更高
  • 业务影响: 对业务影响大的漏洞风险更高

Q: 如何处理误报?

A:

  1. 审查代码上下文,确认是否真的存在安全风险
  2. 如果是误报,添加注释说明为什么是安全的
  3. 可以配置白名单忽略特定规则
  4. 提供反馈改进安全检查规则

Q: 安全审查如何与 CI/CD 集成?

A:

  1. 在 CI 流程中添加安全扫描步骤
  2. 设置安全门禁(如不允许高危漏洞合并)
  3. 定期生成安全报告
  4. 集成 SAST 工具(如 SonarQube、Snyk

📚 相关文档


最后更新: 2026-06-12