Skip to main content
skill CX Codex

sast-scanning — Claude Code skill: static security scans

A skill that walks through static application security testing, so flaws in source code surface before deployment. Handy when you wire a security gate into CI/CD.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill sast-scanning -a claude-code
Open on GitHub

What sast-scanning does

The skill covers how to run static analysis over a codebase. It compares Semgrep, CodeQL, SonarQube, Bandit for Python and Brakeman for Rails, then shows install and run commands for each, custom rule examples, and CI configs.

Semgrep runs with semgrep --config auto . or a ruleset such as p/security-audit and p/owasp-top-ten, and can emit --json or --sarif. CodeQL goes through github/codeql-action in GitHub Actions with a language matrix. SonarQube comes up from a docker-compose.yml alongside postgres:15, and the scanner reads sonar-project.properties.

You need source access, a CI/CD pipeline and the SAST tool installed. Semgrep installs with pip install semgrep or brew install semgrep, Bandit with pip install bandit, Brakeman with gem install brakeman. The Semgrep workflow expects SEMGREP_APP_TOKEN; SonarQube expects SONAR_TOKEN and SONAR_HOST_URL. Miss those and the scan step fails.

What it helps with

  • catch hardcoded passwords and keys in source
  • spot SQL injection before code review
  • add a security gate to GitHub Actions
  • flag unsafe random use in a Python project
  • set up a SonarQube quality gate

Example prompts for the agent

  • Set up Semgrep in CI so semgrep --config p/security-audit . runs on every pull request.
  • Write a custom Semgrep rule for hardcoded passwords and save it to .semgrep/custom-rules.yaml.
  • Bring up SonarQube from docker-compose.yml with postgres:15 and add the scan step to the workflow.

How to install sast-scanning

1Skills CLI (Vercel)

npx skills add BagelHole/DevOps-Security-Agent-Skills --skill sast-scanning -a claude-code

2Manually: put the files in place

~/.claude/skills/sast-scanning/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/sast-scanning/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about sast-scanning

How do I install sast-scanning in Claude Code?

Run npx skills add BagelHole/DevOps-Security-Agent-Skills --skill sast-scanning -a claude-code. The skill file lands at ~/.claude/skills/sast-scanning/SKILL.md.

What does sast-scanning do?

It lays out static application security testing for source code: which tools to pick, how to run them, and how to make the check part of CI/CD.

Which tools does the skill cover?

Semgrep, CodeQL and SonarQube, plus Bandit for Python and Brakeman for Rails. Each one comes with install commands, rule examples and pipeline configs.

Source text

SKILL.md · MIT
---
name: sast-scanning
description: Perform static application security testing with tools like Semgrep, CodeQL, and SonarQube. Identify security vulnerabilities in source code before deployment. Use when implementing secure SDLC, code review automation, or security gates in CI/CD pipelines.
license: MIT
metadata:
  author: devops-skills
  version: "1.0"
---

# 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

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

## Tool Comparison

| Tool | License | Languages | Best For |
|------|---------|-----------|----------|
| Semgrep | OSS/Commercial | 30+ | Custom rules, speed |
| CodeQL | Free (GitHub) | 10+ | Deep analysis |
| SonarQube | OSS/Commercial | 25+ | Quality + Security |
| Bandit | OSS | Python | Python projects |
| Brakeman | OSS | Ruby | Rails apps |

## Semgrep

### Installation

```bash
# Install via pip
pip install semgrep

# Or via Homebrew
brew install semgrep
```

### Basic Usage

```bash
# 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

```yaml
# .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]
    fix: secrets.token_hex()
```

### CI Configuration

```yaml
# .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

```yaml
# .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

```ql
// 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

```yaml
# docker-compose.yml
version: '3.8'

services:
  sonarqube:
    image: sonarqube:lts-community
    ports:
      - "9000:9000"
    environment:
      - SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonar
      - SONAR_JDBC_USERNAME=sonar
      - SONAR_JDBC_PASSWORD=sonar
    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
      - POSTGRES_DB=sonar
    volumes:
      - postgresql_data:/var/lib/postgresql/data

volumes:
  sonarqube_data:
  sonarqube_logs:
  postgresql_data:
```

### Scanner Configuration

```properties
# 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

```yaml
# 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)

```bash
# Install
pip install bandit

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

# With configuration
bandit -r src/ -c bandit.yaml
```

```yaml
# bandit.yaml
skips: ['B101', 'B601']
exclude_dirs: ['tests', 'venv']

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

### JavaScript (ESLint Security)

```bash
# Install
npm install eslint eslint-plugin-security --save-dev
```

```javascript
// .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)

```bash
# Install
gem install brakeman

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

# CI configuration
brakeman --no-exit-on-warn --no-exit-on-error -o report.html
```

## Quality Gates

### SonarQube Quality Gate

```json
{
  "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

```bash
#!/bin/bash
# security-gate.sh

CRITICAL=$(cat results.json | jq '[.results[] | select(.severity == "critical")] | length')
HIGH=$(cat results.json | jq '[.results[] | select(.severity == "high")] | length')

echo "Critical: $CRITICAL, High: $HIGH"

if [ "$CRITICAL" -gt 0 ]; then
  echo "FAILED: Critical vulnerabilities found"
  exit 1
fi

if [ "$HIGH" -gt 5 ]; then
  echo "FAILED: Too many high severity vulnerabilities"
  exit 1
fi

echo "PASSED: Security gate"
exit 0
```

## 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](../../../devops/ci-cd/github-actions/) - CI integration

© devops-skills · MIT · BagelHole/DevOps-Security-Agent-Skills

Similar skills

All skills for Security →

From the same set136

windows-hardening An agent skill that hardens Windows Server to Microsoft security baselines and CIS benchmarks: account policy, Group Policy, Defender, SMB. CX Codex +1 388installs audit-logging A skill for setting up centralized audit logging, retention and SIEM forwarding. Useful when you need an action trail for compliance or incident review. CX Codex +1 385installs redis A skill that walks the agent through Redis setup: caching, queues, Sentinel, cluster mode. Useful when a project needs Redis configured. CX Codex +1 379installs penetration-testing Walks your agent through pentest phases: recon, scanning, exploitation, reporting. Useful when you need to validate your own security controls. CX Codex +1 373installs prompt-injection-defense Defends LLM applications against direct and indirect prompt injection attacks. It is designed for securing RAG pipelines and agentic tool-calling workflows. CX Codex +1 372installs kustomize Customizes Kubernetes manifests declaratively without templating. Helps structure base configurations and environment overlays across dev and production. CX Codex +1 370installs disaster-recovery A skill for disaster recovery planning: RTO and RPO targets, replication strategies, failover drills. Useful when you need a continuity plan on paper. CX Codex +1 367installs kubernetes-hardening Generates hardened Kubernetes manifests with strict security contexts, network policies, and RBAC rules. Useful when preparing workloads for security compliance. CX Codex +1 366installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor