安全体系:secret-audit、credential-gate 与防注入机制

📑 目录

这是「GSD 全景代码解析」专题的第 51 篇。

一、安全威胁模型

AI Agent 工具链面临独特的安全挑战:

graph TD
    A[安全威胁] --> B[数据泄露]
    A --> C[凭据暴露]
    A --> D[注入攻击]
    A --> E[权限提升]
    B --> B1[敏感信息写入代码]
    B --> B2[日志泄露]
    C --> C1[API Key 硬编码]
    C --> C2[环境变量泄露]
    D --> D1[提示词注入]
    D --> D2[间接提示词注入]
    E --> E1[越权文件访问]
    E --> E2[危险命令执行]

二、Secret Audit 系统

secret-audit 是 GSD 的第一道安全防线,负责检测代码中可能泄露的敏感信息。

2.1 检测规则引擎

interface SecretRule {
  name: string;
  pattern: RegExp;
  severity: 'critical' | 'high' | 'medium' | 'low';
  category: 'api_key' | 'password' | 'token' | 'private_key';
}

const SECRET_RULES: SecretRule[] = [
  {
    name: 'OpenAI API Key',
    pattern: /sk-[a-zA-Z0-9]{48}/,
    severity: 'critical',
    category: 'api_key'
  },
  {
    name: 'AWS Access Key',
    pattern: /AKIA[0-9A-Z]{16}/,
    severity: 'critical',
    category: 'api_key'
  },
  {
    name: 'Generic Secret',
    pattern: /(?:password|passwd|pwd)\s*[:=]\s*["'][^"']{8,}["']/i,
    severity: 'high',
    category: 'password'
  },
  {
    name: 'Private Key',
    pattern: /-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/,
    severity: 'critical',
    category: 'private_key'
  }
];

2.2 审计流程

class SecretAuditor {
  async audit(projectPath: string): Promise<AuditResult> {
    const findings: Finding[] = [];
    const files = await this.getAuditFiles(projectPath);
    
    for (const file of files) {
      const content = await fs.readFile(file, 'utf-8');
      
      for (const rule of SECRET_RULES) {
        const matches = content.match(rule.pattern);
        if (matches) {
          findings.push({
            file,
            rule: rule.name,
            severity: rule.severity,
            line: this.getLineNumber(content, matches[0]),
            snippet: this.maskSecret(matches[0])
          });
        }
      }
    }
    
    return { findings, passed: findings.length === 0 };
  }
  
  private maskSecret(secret: string): string {
    if (secret.length <= 8) return '****';
    return secret.slice(0, 4) + '****' + secret.slice(-4);
  }
}

2.3 审计报告示例

═══════════════════════════════════════════════
  GSD Secret Audit Report
═══════════════════════════════════════════════

扫描文件: 127
发现问题: 3

[CRITICAL] OpenAI API Key
  文件: src/config.ts:15
  内容: sk-****1234
  建议: 使用环境变量或密钥管理服务

[HIGH] Generic Secret
  文件: .env:3
  内容: PASSWORD=****
  建议: 将 .env 添加到 .gitignore

[CRITICAL] Private Key
  文件: deploy/key.pem:1
  内容: -----BEGIN PRIVATE KEY-----
  建议: 从仓库中移除,使用 CI/CD 密钥注入

═══════════════════════════════════════════════

三、Credential Gate 凭据门控

credential-gate 确保只有经过授权的 Agent 才能访问敏感操作。

3.1 权限矩阵

Agent读取代码写入代码执行命令访问密钥
Planner
Executor△*
Debugger△*
Auditor
Deployer

*△ 表示需要显式确认的危险操作

3.2 命令白名单机制

const COMMAND_ALLOWLIST: Record<string, string[]> = {
  'Executor': ['npm test', 'npm run build', 'git status'],
  'Debugger': ['npm test', 'node --inspect'],
  'Deployer': ['npm run deploy', 'docker build', 'docker push']
};

class CredentialGate {
  async validateCommand(agent: string, command: string): Promise<boolean> {
    const allowed = COMMAND_ALLOWLIST[agent] || [];
    
    // 精确匹配
    if (allowed.includes(command)) return true;
    
    // 前缀匹配(允许参数)
    const baseCommand = command.split(' ')[0];
    if (allowed.some(a => a.startsWith(baseCommand))) {
      // 需要额外审查参数
      return await this.reviewArguments(agent, command);
    }
    
    return false;
  }
  
  private async reviewArguments(agent: string, command: string): Promise<boolean> {
    // 检查危险参数
    const dangerousFlags = ['-rf', '--force', '> /dev/null', '| sh'];
    if (dangerousFlags.some(f => command.includes(f))) {
      logger.warn(`Dangerous command blocked: ${command}`);
      return false;
    }
    return true;
  }
}

3.3 沙箱执行

class SandboxExecutor {
  async execute(command: string, options: SandboxOptions): Promise<ExecResult> {
    const sandbox = await this.createSandbox({
      readonlyPaths: [options.projectRoot],
      writablePaths: [options.tempDir],
      network: options.allowNetwork ? 'limited' : 'none',
      env: this.sanitizeEnv(process.env)
    });
    
    try {
      return await sandbox.run(command, { timeout: options.timeout || 30000 });
    } finally {
      await sandbox.destroy();
    }
  }
  
  private sanitizeEnv(env: NodeJS.ProcessEnv): Record<string, string> {
    // 移除敏感环境变量
    const sensitive = ['OPENAI_API_KEY', 'AWS_SECRET_KEY', 'GITHUB_TOKEN'];
    const clean = { ...env };
    for (const key of sensitive) {
      delete clean[key];
    }
    return clean;
  }
}

四、提示词注入防御

4.1 输入净化

class PromptSanitizer {
  sanitize(userInput: string): string {
    // 1. 移除控制字符
    let cleaned = userInput.replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f]/g, '');
    
    // 2. 转义特殊标记
    cleaned = cleaned
      .replace(/\{\{/g, '\\{\\{')
      .replace(/\}\}/g, '\\}\\}');
    
    // 3. 检测越狱尝试
    const jailbreakPatterns = [
      /ignore previous instructions/i,
      /you are now \w+/i,
      /DAN|Do Anything Now/i,
      /system:?\s*prompt/i
    ];
    
    for (const pattern of jailbreakPatterns) {
      if (pattern.test(cleaned)) {
        throw new PromptInjectionDetected(pattern.source);
      }
    }
    
    return cleaned;
  }
}

4.2 结构化输出约束

interface SafePrompt {
  system: string;      // 固定系统提示(不可变)
  context: string;     // 项目上下文
  instruction: string; // 任务指令
  userInput: string;   // 已净化的用户输入
  separator: string;   // 明确的分隔符
}

function buildSafePrompt(parts: SafePrompt): string {
  return `${parts.system}

${parts.separator}
CONTEXT:
${parts.context}

${parts.separator}
INSTRUCTION:
${parts.instruction}

${parts.separator}
USER INPUT:
${parts.userInput}

${parts.separator}
IMPORTANT: Only respond within the scope of the instruction above.`;
}

五、安全事件响应

graph LR
    A[检测到安全事件] --> B{严重程度?}
    B -->|Critical| C[立即中止执行]
    B -->|High| D[阻断操作并告警]
    B -->|Medium| E[记录日志并提示]
    B -->|Low| F[仅记录日志]
    C --> G[通知管理员]
    D --> G
    E --> H[继续执行]
    F --> H

六、安全最佳实践

实践实施方式优先级
密钥外置环境变量 + 密钥管理服务P0
最小权限Agent 权限矩阵P0
输入验证PromptSanitizerP0
审计日志所有敏感操作记录P1
定期扫描CI 中的 secret-auditP1
依赖审计npm audit + SnykP1
沙箱执行隔离运行环境P2

下一篇预告: 第 52 篇《漂移检测与 Schema 验证:配置一致性、文档同步与版本兼容性》

我们将深入解析 GSD 如何确保配置、代码与文档三者的一致性,以及 Schema 验证在版本升级中的关键作用。敬请期待。