SuperAPI AI 工具集

static-application-security-testing

安全与审计

查看项目

更新于 10-15 14:25

技能介绍

用途

本技能使智能体能够对源代码仓库执行静态应用安全测试(SAST),在应用未运行的情况下检测安全漏洞。SAST 可在开发生命周期早期发现 SQL 注入、跨站脚本、硬编码密钥、不安全反序列化、密码学误用等问题。

主要能力

  • 检测语言与框架:分析仓库以确定主要语言(Python、JavaScript、Java、Go、C# 等)及所用框架,据此选择适用的 SAST 工具与规则集,并检查已有的工具配置(如 .semgrep.yml、CodeQL 查询包、.bandit 配置文件)。
  • 选择与配置 SAST 工具:针对检测到的技术栈选择工具。Semgrep 用于多语言模式匹配,CodeQL 用于深度语义分析,Bandit 用于 Python 专项检查,ESLint 安全插件用于 JavaScript/TypeScript。加载内置安全规则集及项目自定义规则。
  • 执行静态分析:对代码库运行所选工具,捕获所有发现,包括漏洞类型、受影响文件与行号、严重级别、CWE 标识及问题描述。对大型代码库可并行运行多个工具。
  • 分诊与去重:合并多个工具的结果,去除同一问题的重复检测,将发现分类为真实漏洞、误报或需人工复核。通过上下文分析(例如检查被标记的 SQL 字符串是否真正到达数据库驱动)降低噪声。
  • 生成含修复建议的报告:按严重级别与类别分组,包含易受攻击的代码片段、风险说明、带修正代码的修复建议,以及相关 CWE 条目与 OWASP 类别引用。
  • 集成到 CI 流水线:配置在每次拉取请求或推送到受保护分支时运行扫描,设置质量门禁,在引入严重或高危发现时阻止合并。以 SARIF 格式输出结果,便于与 GitHub Code Scanning、GitLab SAST 或 SonarQube 集成。

支持的技术

  • 多语言:Semgrep(Python、JS/TS、Java、Go、Ruby、C#、PHP、Kotlin、Rust)
  • 深度语义分析:CodeQL(Java、JavaScript、Python、C/C++、C#、Go、Ruby)
  • Python:Bandit、Pylint 安全检查器
  • JavaScript/TypeScript:ESLint(eslint-plugin-security、eslint-plugin-no-secrets)、njsscan
  • Java:SpotBugs 配合 Find Security Bugs 插件、PMD
  • 输出格式:SARIF、JSON、JUnit XML、Markdown
  • CI 平台:GitHub Actions、GitLab CI、Jenkins、Azure DevOps

使用方式

向智能体提供源代码仓库路径,可选指定目标语言、自定义规则文件或用于流水线集成的 CI 平台。智能体将运行相应的 SAST 工具并交付按优先级排序的发现报告。

提示词示例:

Run SAST on the Python application in /app using Semgrep and Bandit. Flag any SQL injection, hardcoded secrets, and insecure deserialization. Output results in SARIF format for GitHub Code Scanning.

示例

示例 1:对 Python Flask 应用运行 Semgrep 扫描

命令:

semgrep scan --config=p/owasp-top-ten --config=p/python --json --output=semgrep-results.json /app

发现(节选):

┌─────────────────────────────────────────────────────────────────┐ │ python.flask.security.injection.sql-injection-with-format-string │ │ Severity: ERROR │ CWE-89 │ OWASP A03:2021 │ ├─────────────────────────────────────────────────────────────────┤ │ /app/routes/users.py:42 │ │ │ │ 40│ def search_users(name): │ │ 41│ query = f"SELECT * FROM users WHERE name = '{name}'"│ │ 42│ result = db.execute(query) │ │ │ │ Fix: Use parameterized queries instead of string formatting. │ ├─────────────────────────────────────────────────────────────────┤ │ python.lang.security.audit.hardcoded-password │ │ Severity: WARNING │ CWE-798 │ OWASP A07:2021 │ ├─────────────────────────────────────────────────────────────────┤ │ /app/config.py:11 │ │ │ │ 10│ class Config: │ │ 11│ DB_PASSWORD = "SuperSecret123!" │ │ 12│ JWT_SECRET = "my-jwt-secret" │ │ │ │ Fix: Load secrets from environment variables or a secrets │ │ manager, never hardcode them in source files. │ └─────────────────────────────────────────────────────────────────┘

SQL 注入发现的修复代码:

BEFORE — vulnerable to SQL injection

def search_users(name): query = f"SELECT * FROM users WHERE name = '{name}'" result = db.execute(query) return result

AFTER — parameterized query

def search_users(name): query = "SELECT * FROM users WHERE name = :name" result = db.execute(text(query), {"name": name}) return result

示例 2:针对 Java 不安全反序列化的 CodeQL 查询

自定义 CodeQL 查询(insecure-deserialization.ql):

/**

  • @name Insecure deserialization of untrusted data
  • @description Deserializing data from an untrusted source without validation
  •          can lead to remote code execution.
    
  • @kind path-problem
  • @problem.severity error
  • @id java/insecure-deserialization
  • @tags security
  •   cwe-502
    
  •   owasp-a08
    

*/

import java import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.UnsafeDeserializationQuery

from UnsafeDeserializationConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Untrusted data from $@ is deserialized here without validation.", source.getNode(), "user-controlled input"

运行查询:

codeql database create java-db --language=java --source-root=/app codeql database analyze java-db insecure-deserialization.ql --format=sarif-latest --output=codeql-results.sarif

发现示例:

/app/src/main/java/com/example/api/ImportController.java:35 ObjectInputStream ois = new ObjectInputStream(request.getInputStream()); Object obj = ois.readObject(); // CWE-502: untrusted deserialization

修复:将 ObjectInputStream 替换为安全替代方案,如带显式类型绑定的 JSON 反序列化,或使用基于允许列表的 ObjectInputFilter。

最佳实践

  • 左移——在每次拉取请求时扫描——在代码审查阶段捕获漏洞比在生产环境发现便宜 10-100 倍。将 SAST 配置为所有受保护分支上的必需 CI 检查。
  • 调整规则以减少误报——从精选的安全规则集(如 Semgrep p/owasp-top-ten)开始,而非启用所有规则。对确认的误报添加带文档说明的抑制。
  • 分层使用多个工具——没有单一 SAST 工具能捕获所有问题。将基于模式的工具(Semgrep)与语义分析工具(CodeQL)结合以获得更广覆盖。每个工具各有优势。
  • 为代码库创建自定义规则——编写项目专属的 Semgrep 或 CodeQL 规则以强制内部安全模式,例如确保所有数据库查询都经过净化包装函数。
  • 使用 SARIF 统一报告——静态分析结果交换格式受 GitHub、GitLab、Azure DevOps 和 SonarQube 支持,无论由哪个工具产生,都能在单一仪表板中查看所有 SAST 发现。

安全边界

  • 仅在用户拥有或明确授权评估的系统上工作,并在测试前记录已批准的范围。
  • 从被动或只读检查开始。在主动扫描、利用、负载生成或破坏性修复之前获得明确批准。
  • 绝不暴露密钥、提取无关数据、削弱生产控制或超出已批准目标。
  • 保留证据、最小化影响、出现不稳定时停止,并为每项重大变更提供回滚或遏制步骤。

边界情况

  • 生成或第三方代码——SAST 工具会标记自动生成的 protobuf 存根、第三方依赖或迁移文件中的问题。使用 .semgrepignore 或 CodeQL 路径过滤器排除这些路径以避免噪声。
  • 模板语言与 DSL——Jinja2 模板、ERB、JSX 及其他模板语言可能无法被所有 SAST 工具完整解析。使用理解模板语法的工具专属插件或补充扫描器。
  • 测试代码中的误报——测试文件常包含故意不安全的模式(如硬编码测试凭据、用于测试设置的原始 SQL)。为测试目录配置单独的规则集或严重级别阈值。
  • 大型 monorepo 扫描缓慢——对百万行 monorepo 进行完整 CodeQL 分析可能耗时超过一小时。使用增量分析,在 PR 上仅扫描变更文件,并在夜间计划运行完整扫描。
  • 历史提交中的密钥——SAST 工具扫描当前工作树,而非 Git 历史。将 SAST 与 Gitleaks 或 TruffleHog 等密钥扫描工具配合使用,以检测过去修订中提交且仍存在于 Git 日志中的凭据。