静态分析与质量门禁
让 Agent 将 SAST、数据流与规则引擎接入 PR:严重级别、基线与误报抑制流程清晰可审计。
SKILL 应列出所用引擎(Semgrep、CodeQL、SpotBugs 等)、扫描路径与语言版本,并约定「阻断」「仅评论」「仅报告」三类结果的处置。
对存量告警采用基线文件或按引入时间过滤,避免新代码与历史债务混在同一门禁下无法推进;新规则上线需附带修复示例或文档链接。
引擎与处置策略
同一 PR 上多种扫描器并存时,Agent 应能按规则 ID 归类、避免重复评论;与依赖扫描、Secret 扫描在安全看板统一优先级。
- 高危(注入、硬编码密钥)默认阻断合并。
- 中低危可配置为 advisory:写入 Checks 摘要或 PR 评论,但不阻塞。
- 引擎版本与规则集在 CI 中钉扎;升级需附带变更说明与样本 diff。
ESLint 完整配置文件示例(.eslintrc.json):
// .eslintrc.json — TypeScript + React 项目推荐配置
{
"env": { "browser": true, "es2022": true, "node": true },
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "react", "react-hooks"],
"rules": {
// 禁止项(error 级别 → 阻断 CI)
"no-console": ["error", { "allow": ["warn", "error"] }],
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-floating-promises": "error",
"no-eval": "error",
// 警告项(warn 级别 → 评论但不阻断)
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"react/prop-types": "off",
// React 18+ 不再需要 import React
"react/react-in-jsx-scope": "off"
},
"ignorePatterns": ["dist/", "coverage/", "*.generated.ts"]
}
基线与误报抑制
基线只收录「已接受风险」或「计划内偿还」项,每条须可追溯到工单;抑制注释必须含工单号与过期复审日期。
- 新代码门禁优先用「仅针对变更集」或 SARIF 中的
new标记,与全量基线分离。 - 误报走规则调整或路径级豁免,禁止无注释的全局关闭。
- 真阳性修复后删除对应基线条目或抑制,避免僵尸条目。
SonarQube 质量门禁配置(Quality Gate)与自定义 ESLint 规则示例:
// SonarQube Quality Gate 阈值配置(sonar-project.properties)
sonar.projectKey=my-app
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.ts,**/*.spec.ts
sonar.coverage.exclusions=**/generated/**,**/migrations/**
# 质量门禁阈值(在 SonarQube UI 或 sonarcloud.io 设置)
# 新代码质量门(推荐,只检查本次变更):
# 覆盖率 > 80% → 阻断
# 重复度 < 3% → 阻断
# 可靠性评级 ≥ A → 阻断
# 安全性评级 ≥ A → 阻断
# 可维护性评级 ≥ A → 警告(不阻断)
// 自定义 ESLint 规则示例(禁止使用 console.log 但允许 console.error)
// rules/no-console-log.js
module.exports = {
meta: {
type: "suggestion",
docs: { description: "禁止使用 console.log(使用 logger.info 替代)" },
schema: [],
messages: { noConsoleLog: "请使用 logger.info() 替代 console.log()" },
},
create(context) {
return {
CallExpression(node) {
if (
node.callee.type === "MemberExpression" &&
node.callee.object.name === "console" &&
node.callee.property.name === "log"
) {
context.report({ node, messageId: "noConsoleLog" });
}
},
};
},
};
pre-commit 集成与 SARIF 上传
将 SARIF 上传到 GitHub Advanced Security、GitLab SAST 或自研聚合器时,Agent 应能根据 fingerprints / partialFingerprints 去重、关联 CWE,并在说明中区分真阳性需修与需规则调整的误报。
- 制品:每个 job 产出独立
.sarif,合并时注意tool.driver与 run 元数据不互相覆盖。 - 严重度映射:将引擎级别映射到平台统一枚举(如
error/warning/note),与合并门禁阈值一致。 - 路径:
originalUriBaseIds与 CI 工作目录对齐,避免 PR 上无法定位行号。 - 门禁:按规则 ID、级别与是否为新引入结果组合策略;可选「仅 fail on new」配合基线文件。
pre-commit hook 集成静态分析(.pre-commit-config.yaml):
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
# ESLint(只检查暂存文件,通过 lint-staged 配合)
- repo: local
hooks:
- id: eslint
name: ESLint
entry: npx eslint --max-warnings 0
language: node
types: [javascript, jsx, ts, tsx]
pass_filenames: true
# Semgrep(本地 SAST,推荐在 CI 中用全量扫描)
- id: semgrep
name: Semgrep
entry: semgrep --config=p/typescript --error
language: python
types: [typescript]
pass_filenames: true
# CI GitHub Actions 完整静态分析(阻断 vs 警告)
# - name: Run ESLint (阻断: error级别)
# run: npx eslint . --max-warnings 0 --format json -o eslint-results.json
# continue-on-error: false # error 级别失败 → 阻断合并
#
# - name: Run Semgrep (警告: 仅评论)
# run: semgrep --config=p/typescript --json > semgrep-results.json
# continue-on-error: true # 不阻断,仅上传 SARIF 作为评论
github/codeql-action/upload-sarif 或第三方 upload 动作;GitLab 使用流水线 artifacts:reports:sast。SKILL 应写明所用动作名与必需字段(sarif_file、category 等)。
PR 合流主流程
固定顺序:扫描 → SARIF 归一化与上传 → 平台去重展示 → 按门禁判定 → 真阳性修复或误报走审计流程。
[ CI:引擎跑扫描,写出 SARIF 2.1.x ]
│
▼
[ 归一化:路径前缀、severity 映射、tool 元数据 ]
│
▼
[ 上传:GH upload-sarif / GL artifacts:reports:sast ]
│
▼
[ 平台:指纹去重 + CWE / 规则 ID 展示 ]
│
┌────────┴────────┐
▼ ▼
[ 门禁:new + 级别阈值 ] [ advisory:评论 / Check 摘要不阻断 ]
│ │
└────────┬────────┘
▼
[ triage:真阳性修代码 / 误报改规则或基线 + PR 审计 ]
│
▼
[ 合流:规则版本归档 + 与 Secret / 依赖扫描同板展示 ]
门禁清单生成器
下方表单仅在本页浏览器内拼接 Markdown,不上传服务器;可用于 PR 描述、SKILL 附录或平台配置评审单。
填写后点击「生成」,再「复制」到剪贴板。
SKILL 片段
---
name: static-analysis-cn
description: 配置静态分析门禁、ESLint/SonarQube/SARIF 与处置策略
---
# 工具约定
- ESLint:error 级别阻断 CI,warn 级别仅评论
- SonarQube:新代码覆盖率 > 80%,可靠性/安全性 ≥ A
- Semgrep:高危规则阻断,中低危 advisory
# 阻断条件(阻止合并)
- ESLint error 级别规则触发
- SonarQube 质量门禁未通过(新代码)
- Semgrep 高危规则(注入、硬编码密钥)
- npm audit 高危 CVE
# 警告条件(评论但不阻断)
- ESLint warn 级别规则
- SonarQube 可维护性问题
- Semgrep 中低危规则
# pre-commit 集成
- 仅扫描暂存文件(lint-staged + pre-commit)
- 本地快速检查,CI 做全量扫描
- 钩子失败时提示修复命令
# 基线与误报
- 新代码用「仅针对变更集」门禁,不混入历史债务
- 抑制注释必须含工单号和复审日期
- 真阳性修复后删除对应基线条目
# SARIF 上传
- GitHub: github/codeql-action/upload-sarif
- GitLab: artifacts:reports:sast
- 路径对齐 originalUriBaseIds 与 CI 工作目录