关于 static-application-security-testing
static-application-security-testing 是供 Agent 检查源代码仓库安全漏洞的技能,无需运行应用。它按语言选择 SAST 工具、分流扫描结果,并可生成报告和配置 CI 集成。
主要功能
- 01检测语言与框架
- 02选择适用的 SAST 工具
- 03静态扫描源代码
- 04分流并去重发现项
- 05生成含修复建议的报告
- 06配置 CI 集成
适用场景
- 01检查仓库中的注入漏洞
- 02整理并审查扫描发现
- 03在 CI 中输出 SARIF 结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ seb1n/ awesome-ai-agent-skills --skill static-application-security-testing安装后在 Claude Code 中输入/static-application-security-testing确认已加载。
详细介绍
静态应用程序安全测试
此技能可让 Agent 对源代码仓库执行静态应用程序安全测试(SAST),在不运行应用程序的情况下检测安全漏洞。Agent 会根据项目使用的语言选择合适的分析工具,使用相关规则集运行扫描,分诊扫描结果以区分真阳性和假阳性,并将结果集成到 CI/CD 流水线中。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:搭配 Find Security Bugs 插件的 SpotBugs、PMD
- 输出格式:SARIF、JSON、JUnit XML、Markdown
- CI 平台:GitHub Actions、GitLab CI、Jenkins、Azure DevOps
用法
向 Agent 提供源代码仓库的路径。也可以指定目标语言、自定义规则文件或用于流水线集成的 CI 平台。Agent 将运行相应的 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
Fix: Replace ObjectInputStream with a safe alternative like JSON deserialization
with explicit type binding, or use an allowlist-based 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)。为测试目录配置单独的规则集或严重性阈值。
- 扫描时间较长的大型单体仓库——对百万行代码的单体仓库进行完整 CodeQL 分析可能耗时超过一小时。使用增量分析,在 PR 中仅扫描更改的文件,并按夜间计划运行完整扫描。
- 历史提交中的机密信息——SAST 工具扫描的是当前工作树,而不是 Git 历史记录。将 SAST 与 Gitleaks 或 TruffleHog 等机密信息扫描工具配合使用,以检测在过去的修订中提交、且仍存在于 Git 日志中的凭据。