security-scanning-security-sast

静态应用程序安全测试(SAST),适用于多语言与多框架的代码漏洞分析。

查看详情
name:security-scanning-security-sastdescription:Static Application Security Testing (SAST) for code vulnerabilitymetadata:globs:"**/*.py, **/*.js, **/*.ts, **/*.java, **/*.rb, **/*.go, **/*.rs, **/*.php"keywords:sast, static analysis, code security, vulnerability scanning, bandit,

SAST Security Plugin

Static Application Security Testing (SAST) for comprehensive code vulnerability detection across multiple languages, frameworks, and security patterns.

Capabilities

  • Multi-language SAST: Python, JavaScript/TypeScript, Java, Ruby, PHP, Go, Rust

  • Tool integration: Bandit, Semgrep, ESLint Security, SonarQube, CodeQL, PMD, SpotBugs, Brakeman, gosec, cargo-clippy

  • Vulnerability patterns: SQL injection, XSS, hardcoded secrets, path traversal, IDOR, CSRF, insecure deserialization

  • Framework analysis: Django, Flask, React, Express, Spring Boot, Rails, Laravel

  • Custom rule authoring: Semgrep pattern development for organization-specific security policies
  • Use this skill when

    Use for code review security analysis, injection vulnerabilities, hardcoded secrets, framework-specific patterns, custom security policy enforcement, pre-deployment validation, legacy code assessment, and compliance (OWASP, PCI-DSS, SOC2).

    Specialized tools: Use security-secrets.md for advanced credential scanning, security-owasp.md for Top 10 mapping, security-api.md for REST/GraphQL endpoints.

    Do not use this skill when

  • You only need runtime testing or penetration testing

  • You cannot access the source code or build outputs

  • The environment forbids third-party scanning tools
  • Instructions

  • Identify the languages, frameworks, and scope to scan.

  • Select SAST tools and configure rules for the codebase.

  • Run scans in CI or locally with reproducible settings.

  • Triage findings, prioritize by severity, and propose fixes.
  • Safety

  • Avoid uploading proprietary code to external services without approval.

  • Require review before enabling auto-fix or blocking releases.
  • SAST Tool Selection

    Python: Bandit

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

    Configuration: .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

    Configuration: .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"
    }
    }

    Multi-Language: 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

    Custom Rules: .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]

    Other Language Tools

    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

    Vulnerability Patterns

    SQL Injection

    VULNERABLE: String formatting/concatenation with user input in SQL queries

    SECURE:

    # Parameterized queries
    cursor.execute("SELECT FROM users WHERE id = %s", (user_id,))
    User.objects.filter(id=user_id) # ORM

    Cross-Site Scripting (XSS)

    VULNERABLE: Direct HTML manipulation with unsanitized user input (innerHTML, outerHTML, document.write)

    SECURE:

    // 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);

    Hardcoded Secrets

    VULNERABLE: Hardcoded API keys, passwords, tokens in source code

    SECURE:

    import os
    API_KEY = os.environ.get('API_KEY')
    PASSWORD = os.getenv('DB_PASSWORD')

    Path Traversal

    VULNERABLE: Opening files using unsanitized user input

    SECURE:

    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()

    Insecure Deserialization

    VULNERABLE: pickle.loads(), yaml.load() with untrusted data

    SECURE:

    import json
    data = json.loads(user_input) # SECURE
    import yaml
    config = yaml.safe_load(user_input) # SECURE

    Command Injection

    VULNERABLE: os.system() or subprocess with shell=True and user input

    SECURE:

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

    Insecure Random

    VULNERABLE: random module for security-critical operations

    SECURE:

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

    Framework Security

    Django

    VULNERABLE: @csrf_exempt, DEBUG=True, weak SECRET_KEY, missing security middleware

    SECURE:

    # 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

    VULNERABLE: debug=True, weak secret_key, CORS wildcard

    SECURE:

    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

    VULNERABLE: Missing helmet, CORS wildcard, no rate limiting

    SECURE:

    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 }));

    Multi-Language Scanner Implementation

    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 Integration

    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
    <div class="overflow-x-auto my-6"><table class="min-w-full divide-y divide-border border border-border"><thead><tr><th class="px-4 py-2 text-left text-sm font-semibold text-foreground bg-muted/50">run:</th></tr></thead><tbody class="divide-y divide-border"><tr><td class="px-4 py-2 text-sm text-foreground">semgrep --config=auto --json --output=semgrep.json</td></tr></tbody></table></div>

    - 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
    <div class="overflow-x-auto my-6"><table class="min-w-full divide-y divide-border border border-border"><thead><tr><th class="px-4 py-2 text-left text-sm font-semibold text-foreground bg-muted/50">- bandit -r . -f json -o bandit.json</th><th class="px-4 py-2 text-left text-sm font-semibold text-foreground bg-muted/50">true</th></tr></thead><tbody class="divide-y divide-border"></tbody></table></div>
    artifacts:
    reports:
    sast: bandit.json

    Best Practices

  • Run early and often - Pre-commit hooks and CI/CD

  • Combine multiple tools - Different tools catch different vulnerabilities

  • Tune false positives - Configure exclusions and thresholds

  • Prioritize findings - Focus on CRITICAL/HIGH first

  • Framework-aware scanning - Use specific rulesets

  • Custom rules - Organization-specific patterns

  • Developer training - Secure coding practices

  • Incremental remediation - Fix gradually

  • Baseline management - Track known issues

  • Regular updates - Keep tools current
  • Related Tools

  • security-secrets.md - Advanced credential detection

  • security-owasp.md - OWASP Top 10 assessment

  • security-api.md - API security testing

  • security-scan.md - Comprehensive security scanning

    1. security-scanning-security-sast - Agent Skills