mcpField
S
security-scanning-security-sast

security-scanning-security-sast

github.com/rmyndharis安全1.9k67 次安装2 周前更新
代码仓库

关于 security-scanning-security-sast

面向代码安全审查的 SAST 技能,覆盖多种语言、框架和常见漏洞模式,并提供扫描器选择与规则配置指导。适合在本地或 CI 中检查代码、分诊发现并提出修复建议。

主要功能

  1. 01覆盖多种编程语言
  2. 02集成多种静态分析工具
  3. 03检测常见代码漏洞
  4. 04提供框架安全检查指导
  5. 05编写 Semgrep 自定义规则
  6. 06指导 CI 扫描与结果分诊

适用场景

  1. 01审查代码中的安全问题
  2. 02部署前检查注入与机密泄露
  3. 03为组织策略编写自定义规则
  4. 04评估遗留代码并安排修复

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rmyndharis/antigravity-skills --skill security-scanning-security-sast

安装后在 Claude Code 中输入/security-scanning-security-sast确认已加载。

详细介绍

SAST 安全插件

静态应用安全测试(SAST),可跨多种语言、框架和安全模式全面检测代码漏洞。

功能

  • 多语言 SAST:Python、JavaScript/TypeScript、Java、Ruby、PHP、Go、Rust
  • 工具集成:Bandit、Semgrep、ESLint Security、SonarQube、CodeQL、PMD、SpotBugs、Brakeman、gosec、cargo-clippy
  • 漏洞模式:SQL 注入、XSS、硬编码密钥、路径遍历、IDOR、CSRF、不安全反序列化
  • 框架分析:Django、Flask、React、Express、Spring Boot、Rails、Laravel
  • 自定义规则编写:开发 Semgrep 模式,制定组织专属的安全策略

适用场景

适用于代码审查安全分析、注入漏洞、硬编码密钥、框架专属模式、自定义安全策略强制执行、部署前验证、遗留代码评估和合规性检查(OWASP、PCI-DSS、SOC2)。

专用工具:使用 security-secrets.md 进行高级凭据扫描,使用 security-owasp.md 进行 Top 10 映射,使用 security-api.md 检查 REST/GraphQL 端点。

不适用场景

  • 仅需运行时测试或渗透测试
  • 无法访问源代码或构建输出
  • 环境禁止使用第三方扫描工具

说明

  1. 确定要扫描的语言、框架和范围。
  2. 选择 SAST 工具,并为代码库配置规则。
  3. 使用可复现的设置,在 CI 或本地运行扫描。
  4. 分类处理发现的问题,按严重程度排序,并提出修复方案。

安全

  • 未经批准,不要将专有代码上传到外部服务。
  • 启用自动修复或阻止发布前,必须经过审查。

SAST 工具选择

Python:Bandit
# Installation & scan
pip install bandit
bandit -r . -f json -o bandit-report.json
bandit -r . -ll -ii -f json  # High/Critical only

配置:.bandit

exclude_dirs: ['/tests/', '/venv/', '/.tox/', '/build/']
tests: [B201, B301, B302, B303, B304, B305, B307, B308, B312, B323, B324, B501, B502, B506, B602, B608]
skips: [B101]
JavaScript/TypeScript:ESLint Security
npm install --save-dev eslint @eslint/plugin-security eslint-plugin-no-secrets
eslint . --ext .js,.jsx,.ts,.tsx --format json > eslint-security.json

配置:.eslintrc-security.json

{
  "plugins": ["@eslint/plugin-security", "eslint-plugin-no-secrets"],
  "extends": ["plugin:security/recommended"],
  "rules": {
    "security/detect-object-injection": "error",
    "security/detect-non-literal-fs-filename": "error",
    "security/detect-eval-with-expression": "error",
    "security/detect-pseudo-random-prng": "error",
    "no-secrets/no-secrets": "error"
  }
}
多语言:Semgrep
pip install semgrep
semgrep --config=auto --json --output=semgrep-report.json
semgrep --config=p/security-audit --json
semgrep --config=p/owasp-top-ten --json
semgrep ci --config=auto  # CI mode

自定义规则:.semgrep.yml

rules:
  - id: sql-injection-format-string
    pattern: cursor.execute("... %s ..." % $VAR)
    message: SQL injection via string formatting
    severity: ERROR
    languages: [python]
    metadata:
      cwe: "CWE-89"
      owasp: "A03:2021-Injection"

  - id: dangerous-innerHTML
    pattern: $ELEM.innerHTML = $VAR
    message: XSS via innerHTML assignment
    severity: ERROR
    languages: [javascript, typescript]
    metadata:
      cwe: "CWE-79"

  - id: hardcoded-aws-credentials
    patterns:
      - pattern: $KEY = "AKIA..."
      - metavariable-regex:
          metavariable: $KEY
          regex: "(aws_access_key_id|AWS_ACCESS_KEY_ID)"
    message: Hardcoded AWS credentials detected
    severity: ERROR
    languages: [python, javascript, java]

  - id: path-traversal-open
    patterns:
      - pattern: open($PATH, ...)
      - pattern-not: open(os.path.join(SAFE_DIR, ...), ...)
      - metavariable-pattern:
          metavariable: $PATH
          patterns:
            - pattern: $REQ.get(...)
    message: Path traversal via user input
    severity: ERROR
    languages: [python]

  - id: command-injection
    patterns:
      - pattern-either:
          - pattern: os.system($CMD)
          - pattern: subprocess.call($CMD, shell=True)
      - metavariable-pattern:
          metavariable: $CMD
          patterns:
            - pattern-either:
                - pattern: $X + $Y
                - pattern: f"...{$VAR}..."
    message: Command injection via shell=True
    severity: ERROR
    languages: [python]
其他语言工具

Java:mvn spotbugs:check Ruby:brakeman -o report.json -f json Go:gosec -fmt=json -out=gosec.json ./... Rust:cargo clippy -- -W clippy::unwrap_used

漏洞模式

SQL 注入

有风险:在 SQL 查询中使用字符串格式化或拼接处理用户输入

安全:

# Parameterized queries
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
User.objects.filter(id=user_id)  # ORM
跨站脚本攻击(XSS)

有风险:直接使用未经净化的用户输入操作 HTML(innerHTML、outerHTML、document.write)

安全:

// Use textContent for plain text
element.textContent = userInput;

// React auto-escapes
<div>{userInput}</div>

// Sanitize when HTML required
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
硬编码密钥

有风险:在源代码中硬编码 API 密钥、密码或令牌

安全:

import os
API_KEY = os.environ.get('API_KEY')
PASSWORD = os.getenv('DB_PASSWORD')
路径遍历

有风险:使用未经净化的用户输入打开文件

安全:

import os
ALLOWED_DIR = '/var/www/uploads'
file_name = request.args.get('file')
file_path = os.path.join(ALLOWED_DIR, file_name)
file_path = os.path.realpath(file_path)
if not file_path.startswith(os.path.realpath(ALLOWED_DIR)):
    raise ValueError("Invalid file path")
with open(file_path, 'r') as f:
    content = f.read()
不安全反序列化

有风险:使用不可信数据调用 pickle.loads()、yaml.load()

安全:

import json
data = json.loads(user_input)  # SECURE
import yaml
config = yaml.safe_load(user_input)  # SECURE
命令注入

有风险:使用 shell=True 和用户输入调用 os.system() 或 subprocess

安全:

subprocess.run(['ping', '-c', '4', user_input])  # Array args
import shlex
safe_input = shlex.quote(user_input)  # Input validation
不安全随机数

有风险:在安全关键操作中使用 random 模块

安全:

import secrets
token = secrets.token_hex(16)
session_id = secrets.token_urlsafe(32)

框架安全

Django

有风险:@csrf_exempt、DEBUG=True、弱 SECRET_KEY、缺少安全中间件

安全:

# settings.py
DEBUG = False
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
X_FRAME_OPTIONS = 'DENY'
Flask

有风险:debug=True、弱 secret_key、CORS 通配符

安全:

import os
from flask_talisman import Talisman

app.secret_key = os.environ.get('FLASK_SECRET_KEY')
Talisman(app, force_https=True)
CORS(app, origins=['https://example.com'])
Express.js

有风险:缺少 helmet、CORS 通配符、没有速率限制

安全:

const helmet = require('helmet');
const rateLimit = require('express-rate-limit');

app.use(helmet());
app.use(cors({ origin: 'https://example.com' }));
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));

多语言扫描器实现

import json
import subprocess
from pathlib import Path
from typing import Dict, List, Any
from dataclasses import dataclass
from datetime import datetime

@dataclass
class SASTFinding:
    tool: str
    severity: str
    category: str
    title: str
    description: str
    file_path: str
    line_number: int
    cwe: str
    owasp: str
    confidence: str

class MultiLanguageSASTScanner:
    def __init__(self, project_path: str):
        self.project_path = Path(project_path)
        self.findings: List[SASTFinding] = []

    def detect_languages(self) -> List[str]:
        """Auto-detect languages"""
        languages = []
        indicators = {
            'python': ['*.py', 'requirements.txt'],
            'javascript': ['*.js', 'package.json'],
            'typescript': ['*.ts', 'tsconfig.json'],
            'java': ['*.java', 'pom.xml'],
            'ruby': ['*.rb', 'Gemfile'],
            'go': ['*.go', 'go.mod'],
            'rust': ['*.rs', 'Cargo.toml'],
        }
        for lang, patterns in indicators.items():
            for pattern in patterns:
                if list(self.project_path.glob(f'**/{pattern}')):
                    languages.append(lang)
                    break
        return languages

    def run_comprehensive_sast(self) -> Dict[str, Any]:
        """Execute all applicable SAST tools"""
        languages = self.detect_languages()

        scan_results = {
            'timestamp': datetime.now().isoformat(),
            'languages': languages,
            'tools_executed': [],
            'findings': []
        }

        self.run_semgrep_scan()
        scan_results['tools_executed'].append('semgrep')

        if 'python' in languages:
            self.run_bandit_scan()
            scan_results['tools_executed'].append('bandit')
        if 'javascript' in languages or 'typescript' in languages:
            self.run_eslint_security_scan()
            scan_results['tools_executed'].append('eslint-security')

        scan_results['findings'] = [vars(f) for f in self.findings]
        scan_results['summary'] = self.generate_summary()
        return scan_results

    def run_semgrep_scan(self):
        """Run Semgrep"""
        for ruleset in ['auto', 'p/security-audit', 'p/owasp-top-ten']:
            try:
                result = subprocess.run([
                    'semgrep', '--config', ruleset, '--json', '--quiet',
                    str(self.project_path)
                ], capture_output=True, text=True, timeout=300)

                if result.stdout:
                    data = json.loads(result.stdout)
                    for f in data.get('results', []):
                        self.findings.append(SASTFinding(
                            tool='semgrep',
                            severity=f.get('extra', {}).get('severity', 'MEDIUM').upper(),
                            category='sast',
                            title=f.get('check_id', ''),
                            description=f.get('extra', {}).get('message', ''),
                            file_path=f.get('path', ''),
                            line_number=f.get('start', {}).get('line', 0),
                            cwe=f.get('extra', {}).get('metadata', {}).get('cwe', ''),
                            owasp=f.get('extra', {}).get('metadata', {}).get('owasp', ''),
                            confidence=f.get('extra', {}).get('metadata', {}).get('confidence', 'MEDIUM')
                        ))
            except Exception as e:
                print(f"Semgrep {ruleset} failed: {e}")

    def generate_summary(self) -> Dict[str, Any]:
        """Generate statistics"""
        severity_counts = {'CRITICAL': 0, 'HIGH': 0, 'MEDIUM': 0, 'LOW': 0}
        for f in self.findings:
            severity_counts[f.severity] = severity_counts.get(f.severity, 0) + 1

        return {
            'total_findings': len(self.findings),
            'severity_breakdown': severity_counts,
            'risk_score': self.calculate_risk_score(severity_counts)
        }

    def calculate_risk_score(self, severity_counts: Dict[str, int]) -> int:
        """Risk score 0-100"""
        weights = {'CRITICAL': 10, 'HIGH': 7, 'MEDIUM': 4, 'LOW': 1}
        total = sum(weights[s] * c for s, c in severity_counts.items())
        return min(100, int((total / 50) * 100))

CI/CD 集成

GitHub Actions
name: SAST Scan
on:
  pull_request:
    branches: [main]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install tools
        run: |
          pip install bandit semgrep
          npm install -g eslint @eslint/plugin-security

      - name: Run scans
        run: |
          bandit -r . -f json -o bandit.json || true
          semgrep --config=auto --json --output=semgrep.json || true

      - name: Upload reports
        uses: actions/upload-artifact@v3
        with:
          name: sast-reports
          path: |
            bandit.json
            semgrep.json
GitLab CI
sast:
  stage: test
  image: python:3.11
  script:
    - pip install bandit semgrep
    - bandit -r . -f json -o bandit.json || true
    - semgrep --config=auto --json --output=semgrep.json || true
  artifacts:
    reports:
      sast: bandit.json

最佳实践

  1. 尽早并频繁运行 - 使用提交前钩子和 CI/CD
  2. 组合使用多种工具 - 不同工具可以发现不同的漏洞
  3. 调整误报 - 配置排除项和阈值
  4. 确定发现项的优先级 - 优先处理 CRITICAL/HIGH 级问题
  5. 感知框架的扫描 - 使用特定的规则集
  6. 自定义规则 - 针对组织的模式
  7. 开发者培训 - 安全编码实践
  8. 增量修复 - 逐步修复
  9. 基线管理 - 跟踪已知问题
  10. 定期更新 - 保持工具处于最新状态

相关工具

  • security-secrets.md - 高级凭据检测
  • security-owasp.md - OWASP Top 10 评估
  • security-api.md - API 安全测试
  • security-scan.md - 全面安全扫描

评论

支持 Markdown