Claude Skills Collection Logo
sickn33-antigravity-awesome-skills

sast-scanning

Perform static application security testing with tools like Semgrep, CodeQL, and SonarQube.
stars49051
forks7120
watches303
updated2026-11-02 21:38:45

SAST Scanning

Identify security vulnerabilities in source code through static analysis.

When to Use This Skill

Use this skill when:

  • Implementing secure SDLC practices
  • Adding security gates to CI/CD
  • Automating code security reviews
  • Finding vulnerabilities before deployment
  • Meeting compliance requirements

Prerequisites

Pin supported scanner/action versions (never use moving @master in production); verify custom-rule/query APIs against that release. The CodeQL class-style query is historical and must be migrated/tested before use. CodeQL availability/licensing depends on repository and product plan. Scanners may download rules, execute builds or upload private source/results: inspect those effects and credentials before scanning untrusted code. A clean SAST result is not a security certification; report language/path/rule coverage and errors.

  • Source code access
  • CI/CD pipeline
  • SAST tool installation

Tool Comparison

ToolLicenseLanguagesBest For
SemgrepOSS/Commercial30+Custom rules, speed
CodeQLFree (GitHub)10+Deep analysis
SonarQubeOSS/Commercial25+Quality + Security
BanditOSSPythonPython projects
BrakemanOSSRubyRails apps

Semgrep

Installation

# Install via pip
pip install semgrep

# Or via Homebrew
brew install semgrep

Basic Usage

# Run with default rules
semgrep --config auto .

# Run specific rulesets
semgrep --config p/security-audit .
semgrep --config p/owasp-top-ten .
semgrep --config p/ci .

# Scan specific languages
semgrep --config p/python .
semgrep --config p/javascript .

# Output formats
semgrep --config auto --json -o results.json .
semgrep --config auto --sarif -o results.sarif .

Custom Rules

# .semgrep/custom-rules.yaml
rules:
  - id: hardcoded-password
    patterns:
      - pattern-either:
          - pattern: password = "..."
          - pattern: PASSWORD = "..."
          - pattern: passwd = "..."
    message: Hardcoded password detected
    severity: ERROR
    languages: [python, javascript, java]
    metadata:
      cwe: "CWE-798"
      owasp: "A3:2017"

  - id: sql-injection
    patterns:
      - pattern: |
          $QUERY = "..." + $USER_INPUT + "..."
          $DB.execute($QUERY)
    message: Potential SQL injection
    severity: ERROR
    languages: [python]
    metadata:
      cwe: "CWE-89"

  - id: insecure-random
    pattern: random.random()
    message: Use secrets module for security-sensitive randomness
    severity: WARNING
    languages: [python]
    # Do not auto-fix: random.random returns a float, token_hex returns text.

CI Configuration

# .github/workflows/semgrep.yml
name: Semgrep

on:
  push:
    branches: [main]
  pull_request:

jobs:
  semgrep:
    runs-on: ubuntu-latest
    container:
      image: returntocorp/semgrep
    steps:
      - uses: actions/checkout@v4

      - name: Run Semgrep
        run: semgrep ci
        env:
          SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}

CodeQL

Setup

# .github/workflows/codeql.yml
name: CodeQL Analysis

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * 0'

jobs:
  analyze:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      actions: read
      contents: read

    strategy:
      matrix:
        language: ['javascript', 'python']

    steps:
      - uses: actions/checkout@v4

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: +security-and-quality

      - name: Autobuild
        uses: github/codeql-action/autobuild@v3

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v3
        with:
          category: "/language:${{ matrix.language }}"

Custom Queries

// queries/sql-injection.ql
/**
 * @name SQL Injection
 * @description User input in SQL query
 * @kind path-problem
 * @problem.severity error
 * @security-severity 9.0
 * @precision high
 * @id py/sql-injection
 * @tags security
 */

import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.security.dataflow.SqlInjectionQuery

from SqlInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "SQL injection from $@.", source.getNode(), "user input"

SonarQube

Docker Setup

# docker-compose.yml
version: '3.8'

services:
  sonarqube:
    image: sonarqube:lts-community
    ports:
      - "127.0.0.1:9000:9000"
    environment:
      - SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonar
      - SONAR_JDBC_USERNAME=sonar
      - SONAR_JDBC_PASSWORD=${SONAR_DB_PASSWORD:?set a protected password}
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_logs:/opt/sonarqube/logs
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=sonar
      - POSTGRES_PASSWORD=${SONAR_DB_PASSWORD:?set a protected password}
      - POSTGRES_DB=sonar
    volumes:
      - postgresql_data:/var/lib/postgresql/data

volumes:
  sonarqube_data:
  sonarqube_logs:
  postgresql_data:

Scanner Configuration

# sonar-project.properties
sonar.projectKey=myproject
sonar.projectName=My Project
sonar.projectVersion=1.0

sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/vendor/**

sonar.language=py
sonar.python.coverage.reportPaths=coverage.xml

sonar.qualitygate.wait=true

CI Integration

# GitHub Actions
- name: SonarQube Scan
  uses: sonarsource/sonarqube-scan-action@master
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

- name: Quality Gate
  uses: sonarsource/sonarqube-quality-gate-action@master
  timeout-minutes: 5
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Language-Specific Tools

Python (Bandit)

# Install
pip install bandit

# Run scan
bandit -r src/ -f json -o bandit-report.json

# With configuration
bandit -r src/ -c bandit.yaml
# bandit.yaml
skips: []  # add only reviewed, scoped suppressions with rationale
exclude_dirs: ['tests', 'venv']

assert_used:
  skips: ['*_test.py', '*_tests.py']

JavaScript (ESLint Security)

# Install
npm install eslint eslint-plugin-security --save-dev
// .eslintrc.js
module.exports = {
  plugins: ['security'],
  extends: ['plugin:security/recommended'],
  rules: {
    'security/detect-object-injection': 'error',
    'security/detect-non-literal-regexp': 'warn',
    'security/detect-unsafe-regex': 'error',
    'security/detect-buffer-noassert': 'error',
    'security/detect-eval-with-expression': 'error',
    'security/detect-no-csrf-before-method-override': 'error',
    'security/detect-possible-timing-attacks': 'warn'
  }
};

Ruby (Brakeman)

# Install
gem install brakeman

# Run scan
brakeman -o brakeman-report.json -f json

# CI configuration
brakeman -o report.html  # preserve failure exit codes in a blocking gate

Quality Gates

SonarQube Quality Gate

{
  "name": "Security Gate",
  "conditions": [
    {
      "metric": "new_security_rating",
      "op": "GT",
      "error": "1"
    },
    {
      "metric": "new_vulnerabilities",
      "op": "GT",
      "error": "0"
    },
    {
      "metric": "new_security_hotspots_reviewed",
      "op": "LT",
      "error": "100"
    }
  ]
}

Custom Gate Script

A gate must validate the selected scanner’s actual JSON/SARIF schema, scan completion, parse errors and findings severities before deciding pass/fail. Missing/malformed output or a failed scanner is an error, never zero findings. Semgrep ERROR/WARNING/INFO are rule severities, not automatically CVSS critical/high. Use the tool’s documented CI exit behavior or a tested schema-specific adapter; do not apply a generic .severity == "critical" query to arbitrary results.

Common Issues

Issue: Too Many False Positives

Problem: Alerts on safe code patterns Solution: Tune rules, add suppressions, use baseline

Issue: Slow Scans

Problem: SAST taking too long in CI Solution: Incremental scanning, parallel execution, exclude test files

Issue: Missing Coverage

Problem: Vulnerabilities not detected Solution: Add custom rules, combine multiple tools

Best Practices

  • Run on every PR/commit
  • Establish baseline for existing code
  • Prioritize by severity and exploitability
  • Maintain custom rules for your codebase
  • Integrate with IDE for early feedback
  • Track trends over time
  • Document false positive suppressions
  • Combine with DAST for comprehensive coverage

Related Skills

  • dast-scanning (dast-scanning) - Dynamic testing
  • dependency-scanning (dependency-scanning) - Dependency vulnerabilities
  • github-actions (github-actions) - CI integration

Limitations

  • Apply guidance only within authorized scope; test destructive steps in non-production first.
  • Docs-only import: upstream scripts and templates not bundled.

Example

# Read-only first: inventory before any active step.
which <tool> && <tool> --help | head -n 20

Adapted from BagelHole/DevOps-Security-Agent-Skills (MIT); frontmatter, When to Use/Limitations, and safety boundaries added for upstream compliance. Docs-only import: helper scripts and templates not bundled.