sast-scanning – Security skill for AI agents
Perform static application security testing with tools like Semgrep, CodeQL, and SonarQube.
Install the sast-scanning skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/sast-scanning-fc669.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /sast-scanning – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/sast-scanning-fc669.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $sast-scanning – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/sast-scanning-fc669.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /sast-scanning – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/sast-scanning-fc669.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /sast-scanning – then describe the task you want done.
SKILL.md content
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
| 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
# Install via pip
pip install semgrep
# Or via Homebrew
brew install semgrepBasic 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=trueCI 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 gateQuality 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 tes
… (full content is in the download package)
Related skills
- scanning-tools – Master essential security scanning tools for network discovery, vulnerability…
- security-and-hardening – Hardens code against vulnerabilities. Use when handling user input, authentication, data…
- security-arsenal – Security payloads, bypass tables, wordlists, gf pattern names, always-rejected bug list…
- security-audit – Comprehensive security auditing workflow covering web application testing, API security…
- security-auditor – Expert security auditor specializing in DevSecOps, comprehensive cybersecurity, and…
- security-automation – Automate security workflows and remediation. Build security pipelines, automate…
- security-bluebook-builder – Build a minimal but real security policy for sensitive apps. The output is a single…
- security-checklist – Review a scoped architecture against evidence-based network, identity, data, secrets…